From 7e69030df17b87950c88e0ee1f9eaa9831cc26b7 Mon Sep 17 00:00:00 2001 From: gojimmypi Date: Mon, 20 Nov 2023 18:05:18 -0800 Subject: [PATCH] Espressif ESP32-C3 ESP32-C6 ESP32-S2 Hardware Acceleration --- IDE/Espressif/ESP-IDF/README.md | 36 +- wolfcrypt/src/aes.c | 49 +- wolfcrypt/src/port/Espressif/README.md | 13 +- wolfcrypt/src/port/Espressif/esp32_aes.c | 369 +++-- wolfcrypt/src/port/Espressif/esp32_mp.c | 1363 ++++++++++++++--- wolfcrypt/src/port/Espressif/esp32_sha.c | 1066 +++++++++++-- wolfcrypt/src/port/Espressif/esp32_util.c | 458 ++++-- wolfcrypt/src/random.c | 3 +- wolfcrypt/src/sha.c | 144 +- wolfcrypt/src/sha256.c | 282 +++- wolfcrypt/src/sha512.c | 99 +- wolfcrypt/src/tfm.c | 34 +- .../wolfcrypt/port/Espressif/esp32-crypt.h | 407 +++-- wolfssl/wolfcrypt/settings.h | 45 +- wolfssl/wolfcrypt/sha256.h | 4 +- wolfssl/wolfcrypt/sha512.h | 3 +- wolfssl/wolfcrypt/tfm.h | 2 + 17 files changed, 3617 insertions(+), 760 deletions(-) diff --git a/IDE/Espressif/ESP-IDF/README.md b/IDE/Espressif/ESP-IDF/README.md index 3117b60eb2..3c6608ed1e 100644 --- a/IDE/Espressif/ESP-IDF/README.md +++ b/IDE/Espressif/ESP-IDF/README.md @@ -14,6 +14,7 @@ Including the following examples: * Simple [TLS client](./examples/wolfssl_client/)/[server](./examples/wolfssl_server/) * Cryptographic [test](./examples/wolfssl_test/) * Cryptographic [benchmark](./examples/wolfssl_benchmark/) +* Bare-bones [template](./examples/template/) The *user_settings.h* file enables some of the hardened settings. @@ -21,7 +22,40 @@ Including the following examples: 1. [ESP-IDF development framework](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/) -## Setup for Linux +## wolfSSL as an Espressif component + +There are various methods available for using wolfSSL as a component: + +* Managed Component - easiest to get started. +* Local component directory - best for development. +* Install locally - least flexible, but project is fully self-contained. + +## Espressif Managed Components + +Visit https://components.espressif.com/components/wolfssl/wolfssl and see the instructions. Typically: + +``` +idf.py add-dependency "wolfssl/wolfssl^5.6.0-stable" +``` + +## Standard local component: + +See the [template example](./examples/template/README.md). Simply created a `wolfssl` directory in the +local project `components` directory and place the [CMakeLists.txt](./examples/template/components/CMakeLists.txt) +file there. Then add a `components/wolfssl/include` directory and place the [user_settings.h](/examples/template/components/wolfssl/include/user_settings.h) +file there. If wolfSSL is in a structure such as `./workspace/wolfssl` with respect to your project at `./workspace/wolfssl`, +then the cmake file should automatically find the wolfSSL source code. Otherwise set the cmake `WOLFSSL_ROOT` variable +in the top-level CMake file. Examples: + +```cmake + set(WOLFSSL_ROOT "C:/some-path/wolfssl") + set(WOLFSSL_ROOT "c:/workspace/wolfssl-[username]") + set(WOLFSSL_ROOT "/mnt/c/somepath/wolfssl") +``` + +See the specific examples for additional details. + +## Setup for Linux (wolfSSL local copy) 1. Run `setup.sh` at _/path/to_`/wolfssl/IDE/Espressif/ESP-IDF/` to deploy files into ESP-IDF tree 2. Find Wolfssl files at _/path/to/esp_`/esp-idf/components/wolfssl/` diff --git a/wolfcrypt/src/aes.c b/wolfcrypt/src/aes.c index 99fda71d20..c31bd76382 100644 --- a/wolfcrypt/src/aes.c +++ b/wolfcrypt/src/aes.c @@ -483,7 +483,7 @@ block cipher mechanism that uses n-bit binary string parameter key with 128-bits #undef WOLFSSL_AES_DIRECT #define WOLFSSL_AES_DIRECT - /* If we choose to never have a fallback to SW: */ + /* Encrypt: If we choose to never have a fallback to SW: */ #if !defined(NEED_AES_HW_FALLBACK) && (defined(HAVE_AESGCM) || defined(WOLFSSL_AES_DIRECT)) static WARN_UNUSED_RESULT int wc_AesEncrypt( /* calling this one when NO_AES_192 is defined */ Aes* aes, const byte* inBlock, byte* outBlock) @@ -501,7 +501,7 @@ block cipher mechanism that uses n-bit binary string parameter key with 128-bits } #endif - /* If we choose to never have a fallback to SW */ + /* Decrypt: If we choose to never have a fallback to SW: */ #if !defined(NEED_AES_HW_FALLBACK) && (defined(HAVE_AES_DECRYPT) && defined(WOLFSSL_AES_DIRECT)) static WARN_UNUSED_RESULT int wc_AesDecrypt( Aes* aes, const byte* inBlock, byte* outBlock) @@ -882,10 +882,9 @@ block cipher mechanism that uses n-bit binary string parameter key with 128-bits #ifdef NEED_AES_TABLES #ifndef WC_AES_BITSLICED -#if (!defined(WOLFSSL_SILABS_SE_ACCEL) && \ - !defined(WOLFSSL_ESP32_CRYPT_RSA_PRI) \ - ) || \ - (defined(WOLFSSL_ESP32_CRYPT_RSA_PRI) && defined(NEED_AES_HW_FALLBACK)) +#if !defined(WOLFSSL_SILABS_SE_ACCEL) || \ + defined(NO_ESP32_CRYPT) || defined(NO_WOLFSSL_ESP32_CRYPT_AES) || \ + defined(NEED_AES_HW_FALLBACK) static const FLASH_QUALIFIER word32 rcon[] = { 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, 0x20000000, 0x40000000, 0x80000000, @@ -1535,8 +1534,8 @@ static WARN_UNUSED_RESULT word32 inv_col_mul( byte t0 = t9 ^ tb ^ td; return t0 ^ AES_XTIME(AES_XTIME(AES_XTIME(t0 ^ te) ^ td ^ te) ^ tb ^ te); } -#endif -#endif +#endif /* HAVE_AES_CBC || WOLFSSL_AES_DIRECT */ +#endif /* WOLFSSL_AES_SMALL_TABLES */ #endif #if defined(HAVE_AES_CBC) || defined(WOLFSSL_AES_DIRECT) || \ @@ -3894,8 +3893,29 @@ static void AesSetKey_C(Aes* aes, const byte* key, word32 keySz, int dir) XMEMCPY(rk, key, keySz); #if defined(LITTLE_ENDIAN_ORDER) && !defined(WOLFSSL_PIC32MZ_CRYPT) && \ (!defined(WOLFSSL_ESP32_CRYPT) || defined(NO_WOLFSSL_ESP32_CRYPT_AES)) - ByteReverseWords(rk, rk, keySz); -#endif + /* Always reverse words when using only SW */ + { + ByteReverseWords(rk, rk, keySz); + } +#else + /* Sometimes reverse words when using supported HW */ + #if defined(WOLFSSL_ESPIDF) + /* Some platforms may need SW fallback (e.g. AES192) */ + #if defined(NEED_AES_HW_FALLBACK) + { + ESP_LOGV(TAG, "wc_AesEncrypt fallback check"); + if (wc_esp32AesSupportedKeyLen(aes)) { + /* don't reverse for HW supported key lengths */ + } + else { + ByteReverseWords(rk, rk, keySz); + } + } + #else + /* If we don't need SW fallback, don't need to reverse words. */ + #endif /* NEED_AES_HW_FALLBACK */ + #endif /* WOLFSSL_ESPIDF */ +#endif /* LITTLE_ENDIAN_ORDER, etc */ switch (keySz) { #if defined(AES_MAX_KEY_SIZE) && AES_MAX_KEY_SIZE >= 128 && \ @@ -4345,13 +4365,20 @@ static void AesSetKey_C(Aes* aes, const byte* key, word32 keySz, int dir) return wc_AesSetKey_for_ESP32(aes, userKey, keylen, iv, dir); } else { + #if defined(WOLFSSL_HW_METRICS) + /* It is interesting to know how many times we could not complete + * AES in hardware due to unsupported lengths. */ + wc_esp32AesUnupportedLengthCountAdd(); + #endif #ifdef DEBUG_WOLFSSL ESP_LOGW(TAG, "wc_AesSetKey HW Fallback, unsupported keylen = %d", keylen); #endif } - #endif + #endif /* WOLFSSL_ESPIDF && NEED_AES_HW_FALLBACK */ + return wc_AesSetKeyLocal(aes, userKey, keylen, iv, dir, 1); + } /* wc_AesSetKey() */ #if defined(WOLFSSL_AES_DIRECT) || defined(WOLFSSL_AES_COUNTER) diff --git a/wolfcrypt/src/port/Espressif/README.md b/wolfcrypt/src/port/Espressif/README.md index 77c096d8ac..d8978f5384 100644 --- a/wolfcrypt/src/port/Espressif/README.md +++ b/wolfcrypt/src/port/Espressif/README.md @@ -8,10 +8,11 @@ For detail about ESP32 HW Acceleration, you can find in [Technical Reference Man ### Building -To enable hw acceleration : +``` +git clone --recurse-submodules -j8 https://github.com/espressif/esp-idf master +``` -* Uncomment out `#define WOLFSSL_ESPIDF` in `/path/to/wolfssl/wolfssl/wolfcrypt/settings.h` -* Uncomment out `#define WOLFSSL_ESP32` in `/path/to/wolfssl/wolfssl/wolfcrypt/settings.h` +Hardware acceleration is enabled by default. To disable portions of the hardware acceleration you can optionally define: @@ -28,7 +29,11 @@ To disable portions of the hardware acceleration you can optionally define: ### Coding -In your application you must include `` before any other wolfSSL headers. If building the sources directly we recommend defining `WOLFSSL_USER_SETTINGS` and adding your own `user_settings.h` file. You can find a good reference for this in `IDE/GCC-ARM/Header/user_settings.h`. +In your application you must include `` before any other wolfSSL headers. +If building the sources directly we recommend defining `WOLFSSL_USER_SETTINGS` and adding your own +`user_settings.h` file. You can find a good reference for this in `IDE/GCC-ARM/Header/user_settings.h`. + +To view disassembly, add `__attribute__((section(".iram1")))` decorator. Foe example: To view disassembly, add `__attribute__((section(".iram1")))` decorator. Foe example: diff --git a/wolfcrypt/src/port/Espressif/esp32_aes.c b/wolfcrypt/src/port/Espressif/esp32_aes.c index 8d677a34f3..84211ee268 100644 --- a/wolfcrypt/src/port/Espressif/esp32_aes.c +++ b/wolfcrypt/src/port/Espressif/esp32_aes.c @@ -23,21 +23,23 @@ * WOLFSSL_SUCCESS and WOLFSSL_FAILURE values should only * be used in the ssl layer, not in wolfCrypt **/ -#include -#include #ifdef HAVE_CONFIG_H #include #endif + +/* Reminder: user_settings.h is needed and included from settings.h + * Be sure to define WOLFSSL_USER_SETTINGS, typically in CMakeLists.txt */ #include +#if defined(WOLFSSL_ESPIDF) /* Entire file is only for Espressif EDP-IDF */ +#include "sdkconfig.h" /* programmatically generated from sdkconfig */ +#include + #ifndef NO_AES -#if defined(WOLFSSL_ESP32_CRYPT) && \ - !defined(NO_WOLFSSL_ESP32_CRYPT_AES) -#include "sdkconfig.h" /* programmatically generated from sdkconfig */ +#if defined(WOLFSSL_ESP32_CRYPT) && !defined(NO_WOLFSSL_ESP32_CRYPT_AES) #include -#include "wolfssl/wolfcrypt/port/Espressif/esp32-crypt.h" #include /* breadcrumb tag text for ESP_LOG() */ @@ -49,21 +51,25 @@ static wolfSSL_Mutex aes_mutex; /* keep track as to whether esp aes is initialized */ static int espaes_CryptHwMutexInit = 0; +#if defined(WOLFSSL_HW_METRICS) + static unsigned long esp_aes_unsupported_length_usage_ct = 0; +#endif + /* * lock hw engine. * this should be called before using engine. * * returns 0 if the hw lock was initialized and mutex lock */ -static int esp_aes_hw_InUse() +static int esp_aes_hw_InUse(void) { - int ret = 0; + int ret = ESP_OK; ESP_LOGV(TAG, "enter esp_aes_hw_InUse"); if (espaes_CryptHwMutexInit == 0) { ret = esp_CryptHwMutexInit(&aes_mutex); - if (ret == 0) { + if (ret == ESP_OK) { /* flag esp aes as initialized */ espaes_CryptHwMutexInit = 1; } @@ -75,8 +81,11 @@ static int esp_aes_hw_InUse() /* esp aes has already been initialized */ } - if (ret == 0) { - /* lock hardware */ + if (ret == ESP_OK) { + /* lock hardware; there should be exactly one instance + * of esp_CryptHwMutexLock(&aes_mutex ...) in code */ + /* TODO - do we really want to wait? + * probably not */ ret = esp_CryptHwMutexLock(&aes_mutex, portMAX_DELAY); } else { @@ -84,15 +93,26 @@ static int esp_aes_hw_InUse() } - if (ret == 0) { + if (ret == ESP_OK) { /* 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); + #if defined(CONFIG_IDF_TARGET_ESP32S2) || \ + defined(CONFIG_IDF_TARGET_ESP32S3) + { + /* Select working mode. Can be typical or DMA. + * 0 => typical + * 1 => DMA */ + DPORT_REG_WRITE(AES_DMA_ENABLE_REG, 0); + } + #elif defined(CONFIG_IDF_TARGET_ESP32C3) || \ + defined(CONFIG_IDF_TARGET_ESP32C6) + { + /* Select working mode. Can be typical or DMA. + * 0 => typical + * 1 => DMA */ + DPORT_REG_WRITE(AES_DMA_ENABLE_REG, 0); + } #endif } @@ -117,11 +137,11 @@ static void esp_aes_hw_Leave( void ) /* * set key to hardware key registers. - * return 0 on success; -1 if mode isn't supported. + * return ESP_OK = 0 on success; BAD_FUNC_ARG if mode isn't supported. */ static int esp_aes_hw_Set_KeyMode(Aes *ctx, ESP32_AESPROCESS mode) { - int ret = 0; + int ret = ESP_OK; word32 i; word32 mode_ = 0; @@ -142,15 +162,20 @@ static int esp_aes_hw_Set_KeyMode(Aes *ctx, ESP32_AESPROCESS mode) } /* if mode */ /* - ** 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 + ** ESP32: see table 22-1 in ESP32 Technical Reference + ** ESP32-S3: see table 19-2 in ESP32-S3 Technical Reference + ** ESP32-C3: + ** ESP32-C6: see table 18-2 in ESP32-C6 Technical Reference + ** + ** Mode Algorithm ESP32 ESP32S3 ESP32C3 ESP32C6 + ** 0 AES-128 Encryption y y y y + ** 1 AES-192 Encryption y n n n + ** 2 AES-256 Encryption y y y y + ** 3 reserved n n n n + ** 4 AES-128 Decryption y y y y + ** 5 AES-192 Decryption y n n n + ** 6 AES-256 Decryption y y y y + ** 7 reserved n n n n */ switch(ctx->keylen){ case 24: mode_ += 1; break; @@ -158,23 +183,52 @@ static int esp_aes_hw_Set_KeyMode(Aes *ctx, ESP32_AESPROCESS mode) default: break; } -#if CONFIG_IDF_TARGET_ESP32S3 - if (mode_ == 1 || mode_ == 5 || mode_ == 7) { + /* Some specific modes are not supported on some targets. */ +#if defined(CONFIG_IDF_TARGET_ESP32) + #define TARGET_AES_KEY_BASE AES_KEY_BASE + if (mode_ == 3 || mode_ > 6) { + /* this should have been detected in aes.c and fall back to SW */ + ESP_LOGE(TAG, "esp_aes_hw_Set_KeyMode unsupported mode: %i", mode_); + ret = BAD_FUNC_ARG; + } + +#elif defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3) + #define TARGET_AES_KEY_BASE AES_KEY_BASE + if (mode_ == 1 || mode_ == 3 || mode_ == 5 || mode_ > 6) { /* this should have been detected in aes.c and fall back to SW */ ESP_LOGE(TAG, "esp_aes_hw_Set_KeyMode unsupported mode: %i", mode_); ret = BAD_FUNC_ARG; } + +#elif defined(CONFIG_IDF_TARGET_ESP32C3) + #define TARGET_AES_KEY_BASE AES_KEY_BASE + if (mode_ == 1 || mode_ == 3|| mode_ == 5 || mode_ > 6) { + /* this should have been detected in aes.c and fall back to SW */ + ESP_LOGE(TAG, "esp_aes_hw_Set_KeyMode unsupported mode: %i", mode_); + ret = BAD_FUNC_ARG; + } +#elif defined(CONFIG_IDF_TARGET_ESP32C6) + #define TARGET_AES_KEY_BASE AES_KEY_0_REG + if (mode_ == 1 || mode_ == 3 || mode_ == 5 || mode_ > 6) { + /* this should have been detected in aes.c and fall back to SW */ + ESP_LOGE(TAG, "esp_aes_hw_Set_KeyMode unsupported mode: %i", mode_); + ret = BAD_FUNC_ARG; + } +#else + /* assume all modes supported, use AES_KEY_BASE */ + #define TARGET_AES_KEY_BASE AES_KEY_BASE #endif - if (ret == 0) { + /* */ + if (ret == ESP_OK) { /* update key */ for (i = 0; i < (ctx->keylen) / sizeof(word32); i++) { - DPORT_REG_WRITE((volatile uint32_t*)(AES_KEY_BASE + (i * 4)), + DPORT_REG_WRITE((volatile word32*)(TARGET_AES_KEY_BASE + (i * 4)), *(((word32*)ctx->key) + i) ); } - if (ret == 0) { + if (ret == ESP_OK) { DPORT_REG_WRITE(AES_MODE_REG, mode_); } ESP_LOGV(TAG, " leave esp_aes_hw_Setkey"); @@ -191,19 +245,38 @@ static int esp_aes_hw_Set_KeyMode(Aes *ctx, ESP32_AESPROCESS mode) */ static void esp_aes_bk(const byte* in, byte* out) { - const word32 *inwords = (const word32 *)in; + const word32* inwords; + uint32_t* outwords; -#if ESP_IDF_VERSION_MAJOR >= 4 - uint32_t *outwords = (uint32_t *)out; -#else - word32 *outwords = (word32 *)out; -#endif + inwords = (const word32*)in; + outwords = (uint32_t*)out; ESP_LOGV(TAG, "enter esp_aes_bk"); -#if CONFIG_IDF_TARGET_ESP32S3 - /* See esp32 - s3 technical reference manual: + +#if defined(CONFIG_IDF_TARGET_ESP32) + /* copy text for encrypting/decrypting blocks */ + DPORT_REG_WRITE(AES_TEXT_BASE, inwords[0]); + DPORT_REG_WRITE(AES_TEXT_BASE + 4, inwords[1]); + DPORT_REG_WRITE(AES_TEXT_BASE + 8, inwords[2]); + DPORT_REG_WRITE(AES_TEXT_BASE + 12, inwords[3]); + + /* start engine */ + DPORT_REG_WRITE(AES_START_REG, 1); + + /* wait until finishing the process */ + while (1) { + if (DPORT_REG_READ(AES_IDLE_REG) == 1) { + break; + } + } + + /* read-out blocks */ + esp_dport_access_read_buffer(outwords, AES_TEXT_BASE, 4); + +#elif defined(CONFIG_IDF_TARGET_ESP32C3) + /* See ESP32-C3 technical reference manual: ** 19.4.3 Operation process using CPU working mode. - ** The ESP32-S3 also supports a DMA mode. + ** The ESP32-C3 also supports a DMA mode. (not ywt implemented) ** ** Copy text for encrypting/decrypting blocks: */ DPORT_REG_WRITE(AES_TEXT_IN_BASE, inwords[0]); @@ -220,26 +293,55 @@ static void esp_aes_bk(const byte* in, byte* out) } /* 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]); - DPORT_REG_WRITE(AES_TEXT_BASE + 8, inwords[2]); - DPORT_REG_WRITE(AES_TEXT_BASE + 12, inwords[3]); + esp_dport_access_read_buffer((uint32_t*)outwords, AES_TEXT_OUT_BASE, 4); +#elif defined(CONFIG_IDF_TARGET_ESP32C6) + /* See ESP32-C6 technical reference manual: + ** 18.4.3 Operation process using CPU working mode. + ** The ESP32-C6 also supports a DMA mode. (not ywt implemented) + ** + ** Copy text for encrypting/decrypting blocks: */ + DPORT_REG_WRITE(AES_TEXT_IN_0_REG, inwords[0]); + DPORT_REG_WRITE(AES_TEXT_IN_1_REG, inwords[1]); + DPORT_REG_WRITE(AES_TEXT_IN_2_REG, inwords[2]); + DPORT_REG_WRITE(AES_TEXT_IN_3_REG, inwords[3]); /* start engine */ - DPORT_REG_WRITE(AES_START_REG, 1); + DPORT_REG_WRITE(AES_TRIGGER_REG, 1); /* wait until finishing the process */ - while (1) { - if (DPORT_REG_READ(AES_IDLE_REG) == 1) { - break; - } + while (DPORT_REG_READ(AES_STATE_REG) != 0) { + /* waiting for the hardware accelerator to complete operation. */ } /* read-out blocks */ - esp_dport_access_read_buffer(outwords, AES_TEXT_BASE, 4); + esp_dport_access_read_buffer(outwords, AES_TEXT_OUT_0_REG, 4); + +#elif defined(CONFIG_IDF_TARGET_ESP32S2) || defined(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) { + /* waiting for the hardware accelerator to complete operation. */ + } + + /* read-out blocks */ + esp_dport_access_read_buffer(outwords, AES_TEXT_OUT_BASE, 4); + +#else + ESP_LOGW(TAG, "Warning: esp_aes_bk called for unsupported target: %s", + CONFIG_IDF_TARGET) + #endif ESP_LOGV(TAG, "leave esp_aes_bk"); @@ -249,36 +351,48 @@ static void esp_aes_bk(const byte* in, byte* out) * wc_esp32AesSupportedKeyLen * @brief: returns 1 if AES key length supported in HW, 0 if not * @param aes:a value of a ley length */ -WOLFSSL_LOCAL int wc_esp32AesSupportedKeyLenValue(int keylen) +int wc_esp32AesSupportedKeyLenValue(int keylen) { - int ret = 0; + int ret = ESP_OK; + #if defined(CONFIG_IDF_TARGET_ESP32) if (keylen == 16 || keylen == 24 || keylen == 32) { ret = 1; } else { - ret = 0; /* keylen 24 (192 bit) not supported */ + ret = ESP_OK; /* keylen 24 (192 bit) not supported */ } -#elif defined(CONFIG_IDF_TARGET_ESP32S2) - ret = 0; /* not supported */ - -#elif defined(CONFIG_IDF_TARGET_ESP32S3) +#elif defined(CONFIG_IDF_TARGET_ESP32C3) if (keylen == 16 || keylen == 32) { ret = 1; } else { - ret = 0; /* keylen 24 (192 bit) not supported */ + ret = ESP_OK; /* keylen 24 (192 bit) not supported */ } -#elif defined(CONFIG_IDF_TARGET_ESP32C3) - ret = 0; /* not supported */ #elif defined(CONFIG_IDF_TARGET_ESP32C6) - ret = 0; /* not supported */ + if (keylen == 16 || keylen == 32) { + ret = 1; + } + else { + ret = ESP_OK; /* keylen 24 (192 bit) not supported */ + } + #elif defined(CONFIG_IDF_TARGET_ESP32H2) - ret = 0; /* not supported */ + ret = ESP_OK; /* not yet implemented */ + +#elif defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3) + if (keylen == 16 || keylen == 32) { + ret = 1; + } + else { + ret = ESP_OK; /* keylen 24 (192 bit) not supported */ + } + #else - ret = 0; /* if we don't know, then it is not supported */ + ret = ESP_OK; /* if we don't know, then it is not supported */ + #endif return ret; } @@ -287,11 +401,11 @@ WOLFSSL_LOCAL int wc_esp32AesSupportedKeyLenValue(int keylen) * wc_esp32AesSupportedKeyLen * @brief: returns 1 if AES key length supported in HW, 0 if not * @param aes: a pointer of the AES object used to encrypt data */ -WOLFSSL_LOCAL int wc_esp32AesSupportedKeyLen(struct Aes* aes) +int wc_esp32AesSupportedKeyLen(struct Aes* aes) { int ret; if (aes == NULL) { - ret = 0; /* we need a valid aes object to get its keylength */ + ret = ESP_OK; /* we need a valid aes object to get its keylength */ } else { ret = wc_esp32AesSupportedKeyLenValue(aes->keylen); @@ -303,28 +417,30 @@ WOLFSSL_LOCAL int wc_esp32AesSupportedKeyLen(struct Aes* aes) * wc_esp32AesEncrypt * @brief: a one block encrypt of the input block, into the output block * @param aes: a pointer of the AES object used to encrypt data -* @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 +* @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. */ -WOLFSSL_LOCAL int wc_esp32AesEncrypt(Aes *aes, const byte* in, byte* out) +int wc_esp32AesEncrypt(Aes *aes, const byte* in, byte* out) { - int ret = 0; + int ret = ESP_OK; ESP_LOGV(TAG, "enter wc_esp32AesEncrypt"); /* lock the hw engine */ ret = esp_aes_hw_InUse(); - if (ret == 0) { + if (ret == ESP_OK) { 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"); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "wc_esp32AesEncrypt failed " + "during esp_aes_hw_Set_KeyMode"); } } /* load the key into the register */ - if (ret == 0) { + if (ret == ESP_OK) { /* process a one block of AES */ esp_aes_bk(in, out); } @@ -338,12 +454,13 @@ WOLFSSL_LOCAL int wc_esp32AesEncrypt(Aes *aes, const byte* in, byte* out) * wc_esp32AesDecrypt * @brief: a one block decrypt of the input block, into the output block * @param aes: a pointer of the AES object used to decrypt data -* @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 +* @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. */ -WOLFSSL_LOCAL int wc_esp32AesDecrypt(Aes *aes, const byte* in, byte* out) +int wc_esp32AesDecrypt(Aes *aes, const byte* in, byte* out) { int ret; @@ -352,14 +469,15 @@ WOLFSSL_LOCAL int wc_esp32AesDecrypt(Aes *aes, const byte* in, byte* out) esp_aes_hw_InUse(); /* load the key into the register */ 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"); + if (ret != ESP_OK) { + 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) { + if (ret == ESP_OK) { /* process a one block of AES */ esp_aes_bk(in, out); /* release hw engine */ @@ -372,16 +490,17 @@ WOLFSSL_LOCAL int wc_esp32AesDecrypt(Aes *aes, const byte* in, byte* out) /* * wc_esp32AesCbcEncrypt * @brief: Encrypts a plain text message from the input buffer, and places the -* resulting cipher text into the output buffer using cipher block chaining -* with AES. +* resulting cipher text into the output buffer using cipher block +* chaining with AES. * @param aes: a pointer of the AES object used to encrypt data -* @param out: a pointer of the output buffer in which to store the cipher text of -* the encrypted message -* @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 +* @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. */ -WOLFSSL_LOCAL int wc_esp32AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) +int wc_esp32AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) { int ret; int i; @@ -396,14 +515,14 @@ WOLFSSL_LOCAL int wc_esp32AesCbcEncrypt(Aes* aes, byte* out, const byte* in, wor ret = esp_aes_hw_InUse(); - if (ret == 0) { + if (ret == ESP_OK) { ret = esp_aes_hw_Set_KeyMode(aes, ESP32_AES_UPDATEKEY_ENCRYPT); - if (ret != 0) { + if (ret != ESP_OK) { ESP_LOGW(TAG, "wc_esp32AesCbcEncrypt failed HW Set KeyMode"); } } /* if set esp_aes_hw_InUse successful */ - if (ret == 0) { + if (ret == ESP_OK) { while (blocks--) { XMEMCPY(temp_block, in + offset, AES_BLOCK_SIZE); @@ -419,7 +538,7 @@ WOLFSSL_LOCAL int wc_esp32AesCbcEncrypt(Aes* aes, byte* out, const byte* in, wor /* store IV for next block */ XMEMCPY(iv, out + offset - AES_BLOCK_SIZE, AES_BLOCK_SIZE); } /* while (blocks--) */ - } /* if Set Mode successful (ret == 0) */ + } /* if Set Mode successful (ret == ESP_OK) */ esp_aes_hw_Leave(); ESP_LOGV(TAG, "leave wc_esp32AesCbcEncrypt"); @@ -429,16 +548,17 @@ WOLFSSL_LOCAL int wc_esp32AesCbcEncrypt(Aes* aes, byte* out, const byte* in, wor /* * wc_esp32AesCbcDecrypt * @brief: Encrypts a plain text message from the input buffer, and places the -* resulting cipher text into the output buffer using cipher block chaining -* with AES. +* resulting cipher text into the output buffer using cipher block +* chaining with AES. * @param aes: a pointer of the AES object used to decrypt data -* @param out: a pointer of the output buffer in which to store the cipher text of -* the decrypted message -* @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 +* @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. */ -WOLFSSL_LOCAL int wc_esp32AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) +int wc_esp32AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) { int ret; @@ -454,14 +574,14 @@ WOLFSSL_LOCAL int wc_esp32AesCbcDecrypt(Aes* aes, byte* out, const byte* in, wor ret = esp_aes_hw_InUse(); - if (ret == 0) { + if (ret == ESP_OK) { ret = esp_aes_hw_Set_KeyMode(aes, ESP32_AES_UPDATEKEY_DECRYPT); - if (ret != 0) { + if (ret != ESP_OK) { ESP_LOGW(TAG, "wc_esp32AesCbcDecrypt failed HW Set KeyMode"); } } - if (ret == 0) { + if (ret == ESP_OK) { while (blocks--) { XMEMCPY(temp_block, in + offset, AES_BLOCK_SIZE); @@ -477,7 +597,7 @@ WOLFSSL_LOCAL int wc_esp32AesCbcDecrypt(Aes* aes, byte* out, const byte* in, wor offset += AES_BLOCK_SIZE; } /* while (blocks--) */ - } /* if Set Mode was successful (ret == 0) */ + } /* if Set Mode was successful (ret == ESP_OK) */ esp_aes_hw_Leave(); ESP_LOGV(TAG, "leave wc_esp32AesCbcDecrypt"); @@ -486,3 +606,40 @@ WOLFSSL_LOCAL int wc_esp32AesCbcDecrypt(Aes* aes, byte* out, const byte* in, wor #endif /* WOLFSSL_ESP32_CRYPT */ #endif /* NO_AES */ + +/* Metrics */ +#if defined(WOLFSSL_ESP32_CRYPT) && !defined(NO_WOLFSSL_ESP32_CRYPT_AES) + +#if defined(WOLFSSL_HW_METRICS) + +/* increment esp_aes_unsupported_length_usage_ct and return current value */ +int wc_esp32AesUnupportedLengthCountAdd(void) { + esp_aes_unsupported_length_usage_ct++; + return esp_aes_unsupported_length_usage_ct; +} + +#endif /* WOLFSSL_HW_METRICS */ + +/* Show AES Metrics when enabled, otherwise callable but no action. */ +int esp_hw_show_aes_metrics(void) +{ + int ret = ESP_OK; + +#if defined(WOLFSSL_HW_METRICS) + + ESP_LOGI(TAG, "--------------------------------------------------------"); + ESP_LOGI(TAG, "------------- wolfSSL ESP HW AES Metrics----------------"); + ESP_LOGI(TAG, "--------------------------------------------------------"); + + ESP_LOGI(TAG, "esp_aes_unsupported_length_usage_ct = %lu", + esp_aes_unsupported_length_usage_ct); +#else + /* no HW math, no HW math metrics */ + +#endif /* WOLFSSL_HW_METRICS */ + + return ret; +} +#endif /* WOLFSSL_ESP32_CRYPT && !NO_WOLFSSL_ESP32_CRYPT_AES */ + +#endif /* WOLFSSL_ESPIDF */ diff --git a/wolfcrypt/src/port/Espressif/esp32_mp.c b/wolfcrypt/src/port/Espressif/esp32_mp.c index 67caac77b7..066c61f685 100644 --- a/wolfcrypt/src/port/Espressif/esp32_mp.c +++ b/wolfcrypt/src/port/Espressif/esp32_mp.c @@ -41,8 +41,14 @@ #ifdef HAVE_CONFIG_H #include #endif + +/* Reminder: user_settings.h is needed and included from settings.h + * Be sure to define WOLFSSL_USER_SETTINGS, typically in CMakeLists.txt */ #include +#if defined(WOLFSSL_ESPIDF) /* Entire file is only for Espressif EDP-IDF */ +#include "sdkconfig.h" /* programmatically generated from sdkconfig */ +#include #include #if !defined(NO_RSA) || defined(HAVE_ECC) @@ -66,12 +72,39 @@ #define ESP_HW_RSAMAX_BIT 4096 #define ESP_HW_MULTI_RSAMAX_BITS 2048 #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*/ + +/* (s+(4-1))/ 4 */ +#define BYTE_TO_WORDS(s) (((s+3)>>2)) + +/* (s+(32-1))/ 8/ 4*/ +#define BITS_TO_WORDS(s) (((s+31)>>3)>>2) + #define BITS_IN_ONE_WORD 32 +#ifndef ESP_RSA_MULM_BITS + #define ESP_RSA_MULM_BITS 16 +#endif + +#ifndef ESP_RSA_EXPT_XBITS + #define ESP_RSA_EXPT_XBITS 8 +#endif + +#ifndef ESP_RSA_EXPT_YBITS + #define ESP_RSA_EXPT_YBITS 8 +#endif + #define ESP_TIMEOUT(cnt) (cnt >= ESP_RSA_TIMEOUT_CNT) +#if defined(CONFIG_IDF_TARGET_ESP32C3) + #include + #include +#elif defined(CONFIG_IDF_TARGET_ESP32C6) + #include +#elif defined(CONFIG_IDF_TARGET_ESP32S2) + #include + #include +#endif + static const char* const TAG = "wolfssl_esp32_mp"; #ifdef DEBUG_WOLFSSL @@ -80,14 +113,16 @@ static const char* const TAG = "wolfssl_esp32_mp"; #define CLR_HW_VALIDATION {hw_validation = 0;} #define IS_HW_VALIDATION (hw_validation == 1) #undef WOLFSSL_HW_METRICS - #define WOLFSSL_HW_METRICS /* usage metrics always on during debug */ + + /* usage metrics always on during debug */ + #define WOLFSSL_HW_METRICS #endif /* For esp_mp_exptmod and esp_mp_mulmod we need a variety of calculated helper ** values to properly setup the hardware. See esp_mp_montgomery_init() */ struct esp_mp_helper { - MATH_INT_T r_inv; /* result of calculated montgomery helper */ + MATH_INT_T r_inv; /* result of calculated Montgomery helper */ word32 exp; word32 Xs; /* how many bits in X operand */ word32 Ys; /* how many bits in Y operand */ @@ -95,28 +130,38 @@ struct esp_mp_helper word32 Rs; /* how many bits in R_inv calc */ word32 maxWords_sz; /* maximum words expected */ word32 hwWords_sz; - mp_digit mp; /* result of calculated montgomery M' helper */ + mp_digit mp; /* result of calculated Montgomery M' helper */ #ifdef DEBUG_WOLFSSL - mp_digit mp2; /* optional compare to alternate montgomery calc */ + mp_digit mp2; /* optional compare to alternate Montgomery calc */ #endif }; +static portMUX_TYPE wc_rsa_reg_lock = portMUX_INITIALIZER_UNLOCKED; + /* usage metrics can be turned on independently of debugging */ #ifdef WOLFSSL_HW_METRICS - static unsigned long esp_mp_mul_usage_ct = 0; - static unsigned long esp_mp_mul_error_ct = 0; - - static unsigned long esp_mp_mulmod_usage_ct = 0; - static unsigned long esp_mp_mulmod_fallback_ct = 0; - static unsigned long esp_mp_mulmod_even_mod_ct = 0; - static unsigned long esp_mp_mulmod_small_x_ct = 0; - static unsigned long esp_mp_mulmod_small_y_ct = 0; - static unsigned long esp_mp_mulmod_error_ct = 0; - - static unsigned long esp_mp_exptmod_usage_ct = 0; - static unsigned long esp_mp_exptmod_error_ct = 0; - static unsigned long esp_mp_exptmod_fallback_ct = 0; static unsigned long esp_mp_max_used = 0; + + static unsigned long esp_mp_mulmod_small_x_ct = 0; + static unsigned long esp_mp_mulmod_small_y_ct = 0; + +#ifndef NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_MP_MUL + static unsigned long esp_mp_mul_usage_ct = 0; + static unsigned long esp_mp_mul_error_ct = 0; + #endif /* !NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_MP_MUL */ + + #ifndef NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_MULMOD + static unsigned long esp_mp_mulmod_usage_ct = 0; + static unsigned long esp_mp_mulmod_fallback_ct = 0; + static unsigned long esp_mp_mulmod_even_mod_ct = 0; + static unsigned long esp_mp_mulmod_error_ct = 0; + #endif /* !NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_MULMOD */ + + #ifndef NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_EXPTMOD + static unsigned long esp_mp_exptmod_usage_ct = 0; + static unsigned long esp_mp_exptmod_error_ct = 0; + static unsigned long esp_mp_exptmod_fallback_ct = 0; + #endif /* !NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_EXPTMOD */ #endif /* mutex */ @@ -146,6 +191,9 @@ struct esp_mp_helper * * See esp_mp_hw_lock(). * +* Note we'll also keep track locally if the lock was called at all. +* For instance, fallback to SW for very small operand and we won't lock HW. +* * When the RSA Accelerator is released from reset, the register RSA_CLEAN_REG * reads 0 and an initialization process begins. Hardware initializes the four * memory blocks by setting them to 0. After initialization is complete, @@ -170,10 +218,17 @@ static int esp_mp_hw_wait_clean(void) /* wait. expected delay 1 to 2 uS */ ESP_EM__MP_HW_WAIT_CLEAN } -#elif defined(CONFIG_IDF_TARGET_ESP32S3) +#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) + ESP_EM__PRE_MP_HW_WAIT_CLEAN + while (!ESP_TIMEOUT(++timeout) && + DPORT_REG_READ(RSA_QUERY_CLEAN_REG) != 1) { + /* wait. expected delay 1 to 2 uS */ + ESP_EM__MP_HW_WAIT_CLEAN + } +#elif defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3) ESP_EM__PRE_MP_HW_WAIT_CLEAN - while (!ESP_TIMEOUT(++timeout) && DPORT_REG_READ(RSA_QUERY_CLEAN_REG) != 1) - { + while (!ESP_TIMEOUT(++timeout) && + DPORT_REG_READ(RSA_QUERY_CLEAN_REG) != 1) { /* wait. expected delay 1 to 2 uS */ ESP_EM__MP_HW_WAIT_CLEAN } @@ -196,15 +251,15 @@ static int esp_mp_hw_wait_clean(void) */ static int esp_mp_hw_islocked(void) { - int ret = 0; + int ret = FALSE; #ifdef SINGLE_THREADED - if (single_thread_locked == 0) { + if (single_thread_locked == FALSE) { /* not in use */ ESP_LOGV(TAG, "SINGLE_THREADED esp_mp_hw_islocked = false"); } else { ESP_LOGV(TAG, "SINGLE_THREADED esp_mp_hw_islocked = true"); - ret = 1; + ret = TRUE; } #else TaskHandle_t mutexHolder = xSemaphoreGetMutexHolder(mp_mutex); @@ -214,7 +269,7 @@ static int esp_mp_hw_islocked(void) } else { ESP_LOGV(TAG, "multi-threaded esp_mp_hw_islocked = true"); - ret = 1; + ret = TRUE; } #endif return ret; @@ -226,7 +281,7 @@ static int esp_mp_hw_islocked(void) * Lock HW engine. * This should be called before using engine. * -* Returns 0 if the HW lock was initialized and mutex lock. +* Returns 0 (ESP_OK) 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 @@ -242,19 +297,19 @@ static int esp_mp_hw_islocked(void) * 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_lock() +static int esp_mp_hw_lock(void) { - int ret = 0; + int ret = ESP_OK; ESP_LOGV(TAG, "enter esp_mp_hw_lock"); #ifdef SINGLE_THREADED - single_thread_locked = 1; + single_thread_locked = TRUE; #else - if (espmp_CryptHwMutexInit == 0) { + if (espmp_CryptHwMutexInit == ESP_OK) { ret = esp_CryptHwMutexInit(&mp_mutex); - if (ret == 0) { + if (ret == ESP_OK) { /* flag esp mp as initialized */ - espmp_CryptHwMutexInit = 1; + espmp_CryptHwMutexInit = TRUE; } else { ESP_LOGE(TAG, "mp mutex initialization failed."); @@ -265,10 +320,13 @@ static int esp_mp_hw_lock() } /* Set our mutex to indicate the HW is in use */ - if (ret == 0) { - /* lock hardware */ + if (ret == ESP_OK) { + /* lock hardware; there should be exactly one instance + * of esp_CryptHwMutexLock(&mp_mutex ...) in code */ + /* TODO - do we really want to wait? + * probably not */ ret = esp_CryptHwMutexLock(&mp_mutex, ESP_MP_HW_LOCK_MAX_DELAY); - if (ret != 0) { + if (ret != ESP_OK) { ESP_LOGE(TAG, "mp engine lock failed."); ret = WC_HW_WAIT_E; /* caller is expected to fall back to SW */ } @@ -277,25 +335,106 @@ static int esp_mp_hw_lock() #if defined(CONFIG_IDF_TARGET_ESP32) /* Enable RSA hardware */ - if (ret == 0) { + if (ret == ESP_OK) { periph_module_enable(PERIPH_RSA_MODULE); + portENTER_CRITICAL_SAFE(&wc_rsa_reg_lock); + { + /* clear bit to enable hardware operation; (set to disable) */ + DPORT_REG_CLR_BIT(DPORT_RSA_PD_CTRL_REG, DPORT_RSA_PD); + ESP_EM__POST_SP_MP_HW_LOCK - /* clear bit to enable hardware operation; (set to disable) */ - DPORT_REG_CLR_BIT(DPORT_RSA_PD_CTRL_REG, DPORT_RSA_PD); - ESP_EM__POST_SP_MP_HW_LOCK + } + portEXIT_CRITICAL_SAFE(&wc_rsa_reg_lock); + } +#elif defined(CONFIG_IDF_TARGET_ESP32C3) + /* Activate the RSA accelerator. See 20.3 of ESP32-C3 technical manual. + * periph_module_enable doesn't seem to be documented and in private folder + * with v5 release. Maybe it will be deprecated? + * + * The ESP32-C3 RSA Accelerator is activated by: + * setting the SYSTEM_CRYPTO_RSA_CLK_EN bit in the SYSTEM_PERIP_CLK_EN1_REG + * register and: + * clearing the SYSTEM_RSA_MEM_PD bit in the SYSTEM_RSA_PD_CTRL_REG reg. + * This releases the RSA Accelerator from reset.*/ + if (ret == ESP_OK) { + periph_module_enable(PERIPH_RSA_MODULE); + portENTER_CRITICAL_SAFE(&wc_rsa_reg_lock); + { + DPORT_REG_SET_BIT((volatile void *)(SYSTEM_PERIP_CLK_EN1_REG), + SYSTEM_CRYPTO_RSA_CLK_EN ); + DPORT_REG_CLR_BIT((volatile void *)(SYSTEM_RSA_PD_CTRL_REG), + SYSTEM_RSA_MEM_PD ); + } + portEXIT_CRITICAL_SAFE(&wc_rsa_reg_lock); + } +#elif defined(CONFIG_IDF_TARGET_ESP32C6) + /* See: 21.3 Functional Description + * + * The RSA accelerator is activated on the ESP32-C6 by: + * setting the PCR_RSA_CLK_EN bit + * and + * clearing the PCR_RSA_RST_EN bit + * in the PCR_RSA_CONF_REG register. + * + * Additionally, users also need to clear PCR_DS_RST_EN bit to + * reset Digital Signature (DS).*/ + if (ret == ESP_OK) { + periph_module_enable(PERIPH_RSA_MODULE); + portENTER_CRITICAL_SAFE(&wc_rsa_reg_lock); + { + /* TODO: When implementing DS (Digital Signature HW), need to + * check if it is in use before disabling: */ + DPORT_REG_CLR_BIT((volatile void *)(PCR_DS_CONF_REG), + PCR_DS_RST_EN ); + + DPORT_REG_SET_BIT((volatile void *)(PCR_RSA_CONF_REG), + PCR_RSA_CLK_EN ); + DPORT_REG_CLR_BIT((volatile void *)(PCR_RSA_CONF_REG), + PCR_RSA_RST_EN ); + } + portEXIT_CRITICAL_SAFE(&wc_rsa_reg_lock); + } +#elif defined(CONFIG_IDF_TARGET_ESP32S2) + /* Activate the RSA accelerator. See 18.3 of ESP32-S2 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 == ESP_OK) { + periph_module_enable(PERIPH_RSA_MODULE); + portENTER_CRITICAL_SAFE(&wc_rsa_reg_lock); + { + /* Note these names are different from those in the documentation! + * + * Documenation lists the same names as the ESP32-C3: + * + * DPORT_REG_SET_BIT((volatile void *)(SYSTEM_PERIP_CLK_EN1_REG), + * SYSTEM_CRYPTO_RSA_CLK_EN ); + * DPORT_REG_CLR_BIT((volatile void *)(SYSTEM_RSA_PD_CTRL_REG), + * SYSTEM_RSA_MEM_PD ); + * + * However, in the sytem_reg.h, the names below were found: + */ + DPORT_REG_SET_BIT((volatile void *)(DPORT_CPU_PERIP_CLK_EN1_REG), + DPORT_CRYPTO_RSA_CLK_EN ); + DPORT_REG_CLR_BIT((volatile void *)(DPORT_RSA_PD_CTRL_REG), + DPORT_RSA_MEM_PD ); + } + portEXIT_CRITICAL_SAFE(&wc_rsa_reg_lock); } #elif defined(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) { + if (ret == ESP_OK) { 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); + portENTER_CRITICAL_SAFE(&wc_rsa_reg_lock); + { + /* clear bit to enable hardware operation; (set to disable) */ + DPORT_REG_CLR_BIT(SYSTEM_RSA_PD_CTRL_REG, SYSTEM_RSA_MEM_PD); + } + portEXIT_CRITICAL_SAFE(&wc_rsa_reg_lock); } #else - /* when unknown or not implmemted, assume there's no HW to lock */ + /* when unknown or not implemented, assume there's no HW to lock */ #endif /* reminder: wait until RSA_CLEAN_REG reads 1 @@ -307,7 +446,7 @@ static int esp_mp_hw_lock() /* ** Release RSA HW engine */ -static int esp_mp_hw_unlock( void ) +static int esp_mp_hw_unlock(void) { int ret = MP_OKAY; if (esp_mp_hw_islocked()) { @@ -318,23 +457,67 @@ static int esp_mp_hw_unlock( void ) /* Disable RSA hardware */ periph_module_disable(PERIPH_RSA_MODULE); +#elif defined(CONFIG_IDF_TARGET_ESP32C3) + /* Deactivate the RSA accelerator. + * See 20.3 of ESP32-C3 technical manual. + * periph_module_enable doesn't seem to be documented and in private + * folder with v5 release. Maybe it will be deprecated? + * The ESP32-C3 RSA Accelerator is activated by: + * setting the SYSTEM_CRYPTO_RSA_CLK_EN bit + * in the SYSTEM_PERIP_CLK_EN1_REG register and: + * clearing the SYSTEM_RSA_MEM_PD bit + * in the SYSTEM_RSA_PD_CTRL_REG reg. + * This releases the RSA Accelerator from reset.*/ + portENTER_CRITICAL_SAFE(&wc_rsa_reg_lock); + { + DPORT_REG_CLR_BIT( + (volatile void *)(DR_REG_RSA_BASE + SYSTEM_CRYPTO_RSA_CLK_EN), + SYSTEM_PERIP_CLK_EN1_REG); + DPORT_REG_SET_BIT( + (volatile void *)(DR_REG_RSA_BASE + SYSTEM_RSA_MEM_PD), + SYSTEM_RSA_PD_CTRL_REG); + } + portEXIT_CRITICAL_SAFE(&wc_rsa_reg_lock); +#elif defined(CONFIG_IDF_TARGET_ESP32C6) + /* TODO: When implementing DS (Digital Signature HW), need to + * notify RSA HW is available. */ + + portENTER_CRITICAL_SAFE(&wc_rsa_reg_lock); + { + DPORT_REG_SET_BIT((volatile void *)(PCR_RSA_CONF_REG), + PCR_RSA_RST_EN); + DPORT_REG_CLR_BIT((volatile void *)(PCR_RSA_CONF_REG), + PCR_RSA_CLK_EN); + } + portEXIT_CRITICAL_SAFE(&wc_rsa_reg_lock); + +#elif defined(CONFIG_IDF_TARGET_ESP32S2) + /* Deactivate the RSA accelerator. + * See 20.3 of ESP32-S3 technical manual. + * periph_module_enable doesn't seem to be documented and is + * in private folder with v5 release. Maybe it will be deprecated? */ + DPORT_REG_SET_BIT(DPORT_RSA_PD_CTRL_REG, DPORT_RSA_MEM_PD); + periph_module_disable(PERIPH_RSA_MODULE); + #elif defined(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? */ + /* Deactivate the RSA accelerator. + * See 20.3 of ESP32-S3 technical manual. + * periph_module_enable doesn't seem to be documented and is + * 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 /* unknown platform, assume no HW to unlock */ -#endif - /* unlock */ + ESP_LOGW(TAG, "Warning: esp_mp_hw_unlock called for unknown target"); +#endif /* per-SoC unlock */ + #if defined(SINGLE_THREADED) - single_thread_locked = 0; + single_thread_locked = FALSE; #else esp_CryptHwMutexUnLock(&mp_mutex); #endif /* SINGLE_THREADED */ - ESP_LOGV(TAG, "esp_mp_hw_unlock"); + ESP_LOGV(TAG, "exit esp_mp_hw_unlock"); } else { ESP_LOGW(TAG, "Warning: esp_mp_hw_unlock called when not locked."); @@ -343,8 +526,7 @@ static int esp_mp_hw_unlock( void ) return ret; } - -/* Only mulmod and mulexp_mod HW accelerator need montgomery math prep: M' */ +/* Only mulmod and mulexp_mod HW accelerator need Montgomery math prep: M' */ #if !defined(NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_EXPTMOD) \ || \ !defined(NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_MULMOD) @@ -352,6 +534,7 @@ static int esp_mp_hw_unlock( void ) static int esp_calc_Mdash(MATH_INT_T *M, word32 k, mp_digit* md) { int ret = MP_OKAY; + ESP_LOGV(TAG, "\nBegin esp_calc_Mdash \n"); #ifdef USE_ALT_MPRIME /* M' = M^(-1) mod b; b = 2^32 */ @@ -429,7 +612,6 @@ static int esp_clean_result(MATH_INT_T* Z, int used_padding) { int ret = MP_OKAY; uint16_t this_extra; - size_t i; /* TODO remove this section if MP_SIZE accepted into sp_int.h ** See https://github.com/wolfSSL/wolfssl/pull/6565 */ @@ -459,9 +641,9 @@ static int esp_clean_result(MATH_INT_T* Z, int used_padding) } /* trim any trailing zeros and adjust z.used size */ - if (Z->used > 1) { + if (Z->used > 0) { ESP_LOGV(TAG, "ZTrim: Z->used = %d", Z->used); - for (i = Z->used; i > 1; i--) { + for (size_t i = Z->used; i > 0; i--) { if (Z->dp[i - 1] == 0) { /* last element in zero based array */ Z->used = i - 1; @@ -504,17 +686,20 @@ static int esp_clean_result(MATH_INT_T* Z, int used_padding) return ret; } -/* start HW process */ -static void process_start(u_int32_t reg) +/* Start HW process. Reg is SoC-specific register. */ +static int process_start(u_int32_t reg) { + int ret = MP_OKAY; /* see 3.16 "software needs to always use the "volatile" ** attribute when accessing registers in these two address spaces. */ - DPORT_REG_WRITE((volatile uint32_t*)reg, 1); + DPORT_REG_WRITE((volatile word32*)reg, 1); ESP_EM__POST_PROCESS_START; + + return ret; } /* wait until RSA math register indicates operation completed */ -static int wait_until_done(uint32_t reg) +static int wait_until_done(word32 reg) { int ret = MP_OKAY; word32 timeout = 0; @@ -526,9 +711,22 @@ static int wait_until_done(uint32_t reg) } ESP_EM__DPORT_FIFO_READ; +#if defined(CONFIG_IDF_TARGET_ESP32C6) + /* Write 1 or 0 to the RSA_INT_ENA_REG register to + * enable or disable the interrupt function. */ + DPORT_REG_WRITE(RSA_INT_CLR_REG, 1); /* write 1 to clear */ + DPORT_REG_WRITE(RSA_INT_ENA_REG, 0); /* disable */ + +#elif defined(CONFIG_IDF_TARGET_ESP32C3) + /* not currently clearing / disable on C3 */ + DPORT_REG_WRITE(RSA_INTERRUPT_REG, 1); + +#else /* clear interrupt */ DPORT_REG_WRITE(RSA_INTERRUPT_REG, 1); +#endif + if (ESP_TIMEOUT(timeout)) { ESP_LOGE(TAG, "rsa operation timed out."); ret = WC_HW_E; /* MP_HW_ERROR; */ @@ -538,42 +736,42 @@ static int wait_until_done(uint32_t reg) } /* read data from memory into mp_init */ -static int esp_memblock_to_mpint(const uint32_t mem_address, +static int esp_memblock_to_mpint(const word32 mem_address, MATH_INT_T* mp, word32 numwords) { int ret = MP_OKAY; - uint32_t i; - #ifdef USE_ESP_DPORT_ACCESS_READ_BUFFER - esp_dport_access_read_buffer((uint32_t*)mp->dp, mem_address, numwords); + esp_dport_access_read_buffer((word32*)mp->dp, mem_address, numwords); #else ESP_EM__PRE_DPORT_READ; DPORT_INTERRUPT_DISABLE(); ESP_EM__READ_NON_FIFO_REG; - for (i = 0; i < numwords; ++i) { + for (volatile word32 i = 0; i < numwords; ++i) { ESP_EM__3_16; - mp->dp[i] = DPORT_SEQUENCE_REG_READ((uint32_t)(mem_address + i * 4)); + mp->dp[i] = DPORT_SEQUENCE_REG_READ( + (volatile word32)(mem_address + i * 4)); } DPORT_INTERRUPT_RESTORE(); #endif mp->used = numwords; #if defined(ESP_VERIFY_MEMBLOCK) - ret = XMEMCMP((const uint32_t *)mem_address, /* HW reg memory */ - (const uint32_t *)&mp->dp, /* our dp value */ + ret = XMEMCMP((const word32 *)mem_address, /* HW reg memory */ + (const word32 *)&mp->dp, /* our dp value */ numwords * sizeof(word32)); - if (ret != 0 ) { + if (ret != ESP_OK) { ESP_LOGW(TAG, "Validation Failure esp_memblock_to_mpint.\n" "Reading %u Words at Address = 0x%08x", (int)(numwords * sizeof(word32)), (unsigned int)mem_address); ESP_LOGI(TAG, "Trying again... "); - esp_dport_access_read_buffer((uint32_t*)mp->dp, mem_address, numwords); + esp_dport_access_read_buffer((word32*)mp->dp, mem_address, numwords); mp->used = numwords; if (0 != XMEMCMP((const void *)mem_address, - (const void *)&mp->dp, numwords * sizeof(word32))) { + (const void *)&mp->dp, + numwords * sizeof(word32))) { ESP_LOGE(TAG, "Validation Failure esp_memblock_to_mpint " "a second time. Giving up."); ret = MP_VAL; @@ -594,11 +792,10 @@ static int esp_memblock_to_mpint(const uint32_t mem_address, static int esp_zero_memblock(u_int32_t mem_address, int wordSz) { int ret = MP_OKAY; - int i; ESP_EM__PRE_DPORT_WRITE; DPORT_INTERRUPT_DISABLE(); - for (i = 0; i < wordSz; i++) { + for (int i=0; i < wordSz; i++) { DPORT_REG_WRITE( (volatile u_int32_t *)(mem_address + (i * sizeof(word32))), (u_int32_t)(0) /* zero memory blocks [wordSz] words long */ @@ -628,7 +825,7 @@ static int esp_mpint_to_memblock(u_int32_t mem_address, /* write */ ESP_EM__PRE_DPORT_WRITE; DPORT_INTERRUPT_DISABLE(); - for (i = 0; i < hwords; i++) { + for (i=0; i < hwords; i++) { if (i < len) { /* write our data */ ESP_LOGV(TAG, "Write i = %d value.", i); @@ -745,7 +942,7 @@ static int esp_get_rinv(MATH_INT_T *rinv, MATH_INT_T *M, word32 exp) ESP_LOGV(TAG, "mp_montgomery_calc_normalization = %d", reti); } else { - ESP_LOGW(TAG, "Error montgomery calc M2 result = %d", reti); + ESP_LOGW(TAG, "Error Montgomery calc M2 result = %d", reti); } } #endif @@ -819,13 +1016,13 @@ int esp_mp_montgomery_init(MATH_INT_T* X, MATH_INT_T* Y, MATH_INT_T* M, } if ((X == NULL) || (Y == NULL) || (M == NULL) ) { /* if a bad oprand passed, we cannot use HW */ - ESP_LOGE(TAG, "ERROR: Bad montgomery operand, falling back to SW"); + ESP_LOGE(TAG, "ERROR: Bad Montgomery operand, falling back to SW"); return MP_HW_FALLBACK; } XMEMSET(mph, 0, sizeof(struct esp_mp_helper)); mph->Xs = mp_count_bits(X); /* X's = the number of bits needed */ -#if ESP_PROHIBIT_SMALL_X +#if (ESP_PROHIBIT_SMALL_X == TRUE) /* optionally prohibit small X. ** note this is very common in ECC: [1] * [Y] mod [M] */ if ((X->used == 1) && (X->dp[1] < (1 << 8))) { @@ -840,33 +1037,55 @@ int esp_mp_montgomery_init(MATH_INT_T* X, MATH_INT_T* Y, MATH_INT_T* M, /* prohibit small Y */ if (ret == MP_OKAY) { - mph->Ys = mp_count_bits(Y); /* init Y's to pass to montgomery init */ - - if (mph->Ys <= 8) { /* hard floor 8 bits, problematic in some ESP32 */ - #ifdef WOLFSSL_HW_METRICS - esp_mp_mulmod_small_y_ct++; /* track how many times we fall back */ - #endif - ESP_LOGV(TAG, "esp_mp_montgomery_init MP_HW_FALLBACK Ys = %d", - mph->Ys); + mph->Ys = mp_count_bits(Y); /* init Y's to pass to Montgomery init */ + + if (mph->Xs <= ESP_RSA_EXPT_XBITS) { + /* hard floor 8 bits, problematic in some older ESP32 chips */ + #ifdef WOLFSSL_HW_METRICS + { + /* track how many times we fall back */ + esp_mp_mulmod_small_x_ct++; + } + #endif + ESP_LOGV(TAG, + "esp_mp_montgomery_init MP_HW_FALLBACK Xs = %d", + mph->Xs); ret = MP_HW_FALLBACK; /* fall back to software calc at exit */ - } + } /* mph->Xs <= ESP_RSA_EXPT_XBITS */ else { - mph->Ms = mp_count_bits(M); - /* maximum bits and words for writing to HW */ - mph->maxWords_sz = bits2words(max(mph->Xs, max(mph->Ys, mph->Ms))); - mph->hwWords_sz = words2hwords(mph->maxWords_sz); - - if ((mph->hwWords_sz << 5) > ESP_HW_RSAMAX_BIT) { - ESP_LOGW(TAG, "Warning: hwWords_sz = %d (%d bits)" - " exceeds HW maximum bits (%d), " - " falling back to SW.", - mph->hwWords_sz, - mph->hwWords_sz << 5, - ESP_HW_RSAMAX_BIT); - ret = MP_HW_FALLBACK; + if (mph->Ys <= ESP_RSA_EXPT_YBITS) { + /* hard floor 8 bits, problematic in some older ESP32 chips */ + #ifdef WOLFSSL_HW_METRICS + { + /* track how many times we fall back */ + esp_mp_mulmod_small_y_ct++; } - } - } + #endif + ESP_LOGV(TAG, + "esp_mp_montgomery_init MP_HW_FALLBACK Ys = %d", + mph->Ys); + ret = MP_HW_FALLBACK; /* fall back to software calc at exit */ + } /* Ys <= ESP_RSA_EXPT_YBITS */ + else { + /* X and Y size ok, continue... */ + mph->Ms = mp_count_bits(M); + /* maximum bits and words for writing to HW */ + mph->maxWords_sz = bits2words(max(mph->Xs, + max(mph->Ys, mph->Ms))); + mph->hwWords_sz = words2hwords(mph->maxWords_sz); + + if ((mph->hwWords_sz << 5) > ESP_HW_RSAMAX_BIT) { + ESP_LOGW(TAG, "Warning: hwWords_sz = %d (%d bits)" + " exceeds HW maximum bits (%d), " + " falling back to SW.", + mph->hwWords_sz, + mph->hwWords_sz << 5, + ESP_HW_RSAMAX_BIT); + ret = MP_HW_FALLBACK; + } /* hwWords_sz check */ + } /* X and Y size ok */ + } /* X size check */ + } /* Prior operation ok */ ESP_LOGV(TAG, "hwWords_sz = %d", mph->hwWords_sz); @@ -876,10 +1095,12 @@ int esp_mp_montgomery_init(MATH_INT_T* X, MATH_INT_T* Y, MATH_INT_T* M, */ #if defined(CONFIG_IDF_TARGET_ESP32) exp = mph->hwWords_sz << 6; -#elif defined(CONFIG_IDF_TARGET_ESP32S3) +#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) + exp = mph->maxWords_sz * BITS_IN_ONE_WORD * 2; +#elif defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3) exp = mph->maxWords_sz * BITS_IN_ONE_WORD * 2; #else - exp = 0; /* no HW, no montgomery HW init */ + exp = 0; /* no HW, no Montgomery HW init */ #endif if (ret == MP_OKAY && (M != NULL)) { @@ -974,14 +1195,15 @@ int esp_mp_mul(MATH_INT_T* X, MATH_INT_T* Y, MATH_INT_T* Z) #endif int ret = MP_OKAY; /* assume success until proven wrong */ + int mp_mul_lock_called = FALSE; /* May fall back to SW; track if locked */ /* we don't use the mph helper for mp_mul, so we'll calculate locally: */ word32 Xs; word32 Ys; word32 Zs; - word32 maxWords_sz; - word32 hwWords_sz; - word32 resultWords_sz; + word32 maxWords_sz = 0; + word32 hwWords_sz = 0; + word32 resultWords_sz = 0; #if defined(CONFIG_IDF_TARGET_ESP32) word32 left_pad_offset = 0; @@ -1043,7 +1265,7 @@ int esp_mp_mul(MATH_INT_T* X, MATH_INT_T* Y, MATH_INT_T* Z) ESP_LOGE(TAG, "Caller must not try HW when validation active."); } else { - SET_HW_VALIDATION; + SET_HW_VALIDATION; /* force next mp_mul to SW for compare */ mp_mul(X2, Y2, Z2); CLR_HW_VALIDATION; } @@ -1057,30 +1279,29 @@ int esp_mp_mul(MATH_INT_T* X, MATH_INT_T* Y, MATH_INT_T* Z) * with operand length N = 32 × x, * where x ∈ {1, 2, 3, . . . , 64} */ if (Xs > 64 || Ys > 64) { - return MP_HW_FALLBACK; + return MP_HW_FALLBACK; /* TODO add count metric on size fallback */ } if (Zs <= sizeof(mp_digit)*8) { Z->dp[0] = X->dp[0] * Y->dp[0]; Z->used = 1; #if defined(WOLFSSL_SP_INT_NEGATIVE) || defined(USE_FAST_MATH) - Z->sign = res_sign; /* see above mp_isneg() for negative result detection */ + Z->sign = res_sign; /* See above mp_isneg() for negative detection */ #endif return MP_OKAY; } if (ret == MP_OKAY) { - - } - /* maximum bits and words for writing to HW */ - maxWords_sz = bits2words(max(Xs, Ys)); - hwWords_sz = words2hwords(maxWords_sz); - - resultWords_sz = bits2words(Xs + Ys); - /* sanity check */ - if((hwWords_sz<<5) > ESP_HW_MULTI_RSAMAX_BITS) { - ESP_LOGW(TAG, "exceeds max bit length(2048) (a)"); - ret = MP_HW_FALLBACK; /* Error: value is not able to be used. */ + /* maximum bits and words for writing to HW */ + maxWords_sz = bits2words(max(Xs, Ys)); + hwWords_sz = words2hwords(maxWords_sz); + + resultWords_sz = bits2words(Xs + Ys); + /* sanity check */ + if((hwWords_sz << 5) > ESP_HW_MULTI_RSAMAX_BITS) { + ESP_LOGW(TAG, "exceeds max bit length(2048) (a)"); + ret = MP_HW_FALLBACK; /* Error: value is not able to be used. */ + } } #if defined(CONFIG_IDF_TARGET_ESP32) @@ -1093,8 +1314,9 @@ int esp_mp_mul(MATH_INT_T* X, MATH_INT_T* Y, MATH_INT_T* Z) * need to write data to each memory block only according to the length * of the number. * 4. Write 1 to MUL_START_REG - * 5. Wait for the first operation to be done. Poll INTERRUPT_REG until it reads 1. - * (Or until the INTER interrupt is generated.) + * 5. Wait for the first operation to be done. + * Poll INTERRUPT_REG until it reads 1. + * (Or until the INTER interrupt is generated.) * 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. @@ -1129,9 +1351,21 @@ int esp_mp_mul(MATH_INT_T* X, MATH_INT_T* Y, MATH_INT_T* Z) } } + /* lock HW for use, enable peripheral clock */ if (ret == MP_OKAY) { - /* lock HW for use */ - ret = esp_mp_hw_lock(); /* enables HW clock */ + mp_mul_lock_called = TRUE; /* we'll not try to unlock + * unless we locked it here. */ + #ifdef WOLFSSL_HW_METRICS + { + /* Only track max values when using HW */ + esp_mp_max_used = (X->used > esp_mp_max_used) ? X->used : + esp_mp_max_used; + esp_mp_max_used = (Y->used > esp_mp_max_used) ? Y->used : + esp_mp_max_used; + } + #endif + + ret = esp_mp_hw_lock(); } if (ret == MP_OKAY) { @@ -1184,7 +1418,194 @@ int esp_mp_mul(MATH_INT_T* X, MATH_INT_T* Y, MATH_INT_T* Z) } #endif } /* end of processing */ -#elif defined(CONFIG_IDF_TARGET_ESP32S3) +#elif defined(CONFIG_IDF_TARGET_ESP32C3) + /* Unlike the ESP32 that is limited to only four operand lengths, + * the ESP32-C3 The RSA Accelerator supports large-number modular + * multiplication with operands of 128 different lengths. + * + * X & Y must be represented by the same number of bits. Must be + * enough to represent the larger one. */ + + /* Figure out how many words we need to + * represent each operand & the result. */ + + /* Make sure we are within capabilities of hardware. */ + if ((hwWords_sz * BITS_IN_ONE_WORD) > ESP_HW_MULTI_RSAMAX_BITS) { + ESP_LOGW(TAG, "exceeds max bit length(%d)", ESP_HW_MULTI_RSAMAX_BITS); + ret = MP_HW_FALLBACK; /* let SW figure out how to deal with it */ + } + if ((hwWords_sz * BITS_IN_ONE_WORD * 2) > ESP_HW_RSAMAX_BIT) { + ESP_LOGW(TAG, "result exceeds max bit length(%d)", ESP_HW_RSAMAX_BIT ); + ret = MP_HW_FALLBACK; /* let SW figure out how to deal with it */ + } + + /* Steps to perform large number multiplication. Calculates Z = 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 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 as 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. */ + /* lock HW for use, enable peripheral clock */ + if (ret == MP_OKAY) { + mp_mul_lock_called = TRUE; /* Do not try to unlock unless we locked */ + #ifdef WOLFSSL_HW_METRICS + { + /* Only track max values when using HW */ + esp_mp_max_used = (X->used > esp_mp_max_used) ? X->used : + esp_mp_max_used; + esp_mp_max_used = (Y->used > esp_mp_max_used) ? Y->used : + esp_mp_max_used; + } + #endif + + ret = esp_mp_hw_lock(); + } /* the only thing we expect is success or busy */ + if (ret == MP_OKAY) { + ret = esp_mp_hw_wait_clean(); + } + + /* HW multiply */ + if (ret == MP_OKAY) { + /* 2. Disable completion interrupt signal; we don't use. + ** 0 => no interrupt; 1 => interrupt on completion. */ + DPORT_REG_WRITE(RSA_INTERRUPT_REG, 0); + + /* 3. Write number of words required for result. */ + DPORT_REG_WRITE(RSA_LENGTH_REG, (hwWords_sz * 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, + Xs, + hwWords_sz); + esp_mpint_to_memblock(RSA_MEM_Z_BLOCK_BASE + hwWords_sz * 4, + Y, + Ys, + hwWords_sz); + + /* 5. Start operation and wait until it completes. */ + process_start(RSA_MULT_START_REG); + ret = wait_until_done(RSA_QUERY_INTERRUPT_REG); + } + if (ret == MP_OKAY) { + /* 6. read the result form MEM_Z */ + esp_memblock_to_mpint(RSA_MEM_Z_BLOCK_BASE, Z, resultWords_sz); + } +#elif defined(CONFIG_IDF_TARGET_ESP32C6) + /* Unlike the ESP32 that is limited to only four operand lengths, + * the ESP32-C6 The RSA Accelerator supports large-number modular + * multiplication with operands of 128 different lengths. + * + * X & Y must be represented by the same number of bits. Must be + * enough to represent the larger one. */ + + /* Figure out how many words we need to + * represent each operand & the result. */ + + /* Make sure we are within capabilities of hardware. */ + if ((hwWords_sz * BITS_IN_ONE_WORD) > ESP_HW_MULTI_RSAMAX_BITS) { + ESP_LOGW(TAG, "exceeds max bit length(%d)", ESP_HW_MULTI_RSAMAX_BITS); + ret = MP_HW_FALLBACK; /* let SW figure out how to deal with it */ + } + if ((hwWords_sz * BITS_IN_ONE_WORD * 2) > ESP_HW_RSAMAX_BIT) { + ESP_LOGW(TAG, "result exceeds max bit length(%d)", ESP_HW_RSAMAX_BIT ); + ret = MP_HW_FALLBACK; /* let SW figure out how to deal with it */ + } + + /* Steps to perform large number multiplication. Calculates Z = 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. */ + /* lock HW for use, enable peripheral clock */ + if (ret == MP_OKAY) { + mp_mul_lock_called = TRUE; /* Do not try to unlock unless we locked */ + #ifdef WOLFSSL_HW_METRICS + { + /* Only track max values when using HW */ + esp_mp_max_used = (X->used > esp_mp_max_used) ? X->used : + esp_mp_max_used; + esp_mp_max_used = (Y->used > esp_mp_max_used) ? Y->used : + esp_mp_max_used; + } + #endif + + ret = esp_mp_hw_lock(); + } /* the only thing we expect is success or busy */ + + if (ret == MP_OKAY) { + ret = esp_mp_hw_wait_clean(); + } + + /* HW multiply */ + if (ret == MP_OKAY) { + /* 1. Disable completion interrupt signal; we don't use. + * Write 1 (enable) or 0 (disable) to the RSA_INT_ENA_REG register. + * 0 => no interrupt; 1 => interrupt on completion. */ + DPORT_REG_WRITE(RSA_INT_ENA_REG, 0); + /* 2. Write number of words required for result. */ + /* see 21.3.3 Write (/N16 − 1) to the RSA_MODE_REG register */ + DPORT_REG_WRITE(RSA_MODE_REG, (hwWords_sz * 2 - 1)); + + /* 3. Write Xi and Yi for ∈ {0, 1, . . . , n − 1} to memory blocks + * RSA_X_MEM and RSA_Z_MEM + * Maximum is 64 words (64*8*4 = 2048 bits) */ + esp_mpint_to_memblock(RSA_X_MEM, + X, + Xs, + hwWords_sz); + esp_mpint_to_memblock(RSA_Z_MEM + hwWords_sz * 4, + Y, + Ys, + hwWords_sz); + + /* 4. Write 1 to the RSA_SET_START_MULT register */ + ret = process_start(RSA_SET_START_MULT_REG); + + } + /* 5. Wait for the completion of computation, which happens when the + * content of RSA_QUERY_IDLE becomes 1 or the RSA interrupt occurs. */ + if (ret == MP_OKAY) { + ret = wait_until_done(RSA_QUERY_IDLE_REG); + } + + if (ret == MP_OKAY) { + /* 6. read the result from MEM_Z */ + esp_memblock_to_mpint(RSA_Z_MEM, Z, resultWords_sz); + } + /* end ESP32-C6 */ + +#elif defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3) /* Unlike the ESP32 that is limited to only four operand lengths, * the ESP32-S3 The RSA Accelerator supports large-number modular * multiplication with operands of 128 different lengths. @@ -1205,25 +1626,40 @@ int esp_mp_mul(MATH_INT_T* X, MATH_INT_T* Y, MATH_INT_T* Z) ret = MP_HW_FALLBACK; /* let SW figure out how to deal with it */ } - /* 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. + /* Steps to perform large number multiplication. Calculates Z = 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). + * 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). + * 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 == MP_OKAY) { - ret = esp_mp_hw_lock(); /* enables HW clock */ + mp_mul_lock_called = TRUE; /* Don't try to unlock unless we locked. */ + #ifdef WOLFSSL_HW_METRICS + { + /* Only track max values when using HW */ + esp_mp_max_used = (X->used > esp_mp_max_used) ? X->used : + esp_mp_max_used; + esp_mp_max_used = (Y->used > esp_mp_max_used) ? Y->used : + esp_mp_max_used; + } + #endif + + ret = esp_mp_hw_lock(); } /* the only thing we expect is success or busy */ if (ret == MP_OKAY) { ret = esp_mp_hw_wait_clean(); @@ -1267,7 +1703,12 @@ int esp_mp_mul(MATH_INT_T* X, MATH_INT_T* Y, MATH_INT_T* Z) /* common exit for all chipset types */ /* step.7 clear and release HW */ - esp_mp_hw_unlock(); + if (mp_mul_lock_called) { + ret = esp_mp_hw_unlock(); + } + else { + ESP_LOGV(TAG, "Lock not called"); + } #if defined(WOLFSSL_SP_INT_NEGATIVE) || defined(USE_FAST_MATH) if (ret == MP_OKAY) { @@ -1283,6 +1724,12 @@ int esp_mp_mul(MATH_INT_T* X, MATH_INT_T* Y, MATH_INT_T* Z) } #endif + if (ret == MP_OKAY) { + /* never clean the result for anything other than success, as we may + * fall back to SW and we don't want to muck up operand values. */ + esp_clean_result(Z, 0); + } + #ifdef DEBUG_WOLFSSL if (mp_cmp(X, X2) != 0) { /* this may be interesting when operands change (e.g. z=x*z mode m) */ @@ -1307,8 +1754,8 @@ int esp_mp_mul(MATH_INT_T* X, MATH_INT_T* Y, MATH_INT_T* Z) ESP_LOGI(TAG, "left_pad_offset = %d", left_pad_offset); #endif ESP_LOGI(TAG, "hwWords_sz<<2 = %d", hwWords_sz << 2); - esp_show_mp("X", X2); /* show the copy in X2, as X may have been clobbered */ - esp_show_mp("Y", Y2); /* show the copy in Y2, as Y may have been clobbered */ + esp_show_mp("X", X2); /* show X2 copy, as X may have been clobbered */ + esp_show_mp("Y", Y2); /* show Y2 copy, as Y may have been clobbered */ esp_show_mp("Peek Z", PEEK); /* this is the Z before start */ esp_show_mp("Z", Z); /* this is the HW result */ esp_show_mp("Z2", Z2); /* this is the SW result */ @@ -1329,17 +1776,11 @@ int esp_mp_mul(MATH_INT_T* X, MATH_INT_T* Y, MATH_INT_T* Z) } #endif - if (ret == MP_OKAY) { - /* never clean the result for anything other than success, as we may - * fall back to SW and we don't want to muck up operand values. */ - esp_clean_result(Z, 0); - } - ESP_LOGV(TAG, "\nEnd esp_mp_mul \n"); return ret; } /* esp_mp_mul() */ -#endif /* ! NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_MP_MUL*/ +#endif /* Use HW mp_mul: ! NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_MP_MUL*/ #ifndef NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_MULMOD /* Large Number Modular Multiplication @@ -1350,17 +1791,18 @@ int esp_mp_mul(MATH_INT_T* X, MATH_INT_T* Y, MATH_INT_T* Z) int esp_mp_mulmod(MATH_INT_T* X, MATH_INT_T* Y, MATH_INT_T* M, MATH_INT_T* Z) { struct esp_mp_helper mph[1]; /* we'll save some values in this mp helper */ - MATH_INT_T tmpZ[1] = {}; + MATH_INT_T tmpZ[1] = { }; #ifdef DEBUG_WOLFSSL - MATH_INT_T X2[1] = {}; - MATH_INT_T Y2[1] = {}; - MATH_INT_T M2[1] = {}; - MATH_INT_T Z2[1] = {}; - MATH_INT_T PEEK[1] = {}; + MATH_INT_T X2[1] = { }; + MATH_INT_T Y2[1] = { }; + MATH_INT_T M2[1] = { }; + MATH_INT_T Z2[1] = { }; + MATH_INT_T PEEK[1] = { }; (void) PEEK; #endif int ret = MP_OKAY; + int mulmod_lock_called = FALSE; word32 zwords = 0; #if defined(WOLFSSL_SP_INT_NEGATIVE) || defined(USE_FAST_MATH) @@ -1372,8 +1814,12 @@ int esp_mp_mulmod(MATH_INT_T* X, MATH_INT_T* Y, MATH_INT_T* M, MATH_INT_T* Z) #endif #if defined(CONFIG_IDF_TARGET_ESP32) -#elif defined(CONFIG_IDF_TARGET_ESP32S3) - uint32_t OperandBits; + +#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) + word32 OperandBits; + int WordsForOperand; +#elif defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3) + word32 OperandBits; int WordsForOperand; #else ret = MP_HW_FALLBACK; @@ -1381,12 +1827,6 @@ int esp_mp_mulmod(MATH_INT_T* X, MATH_INT_T* Y, MATH_INT_T* M, MATH_INT_T* Z) ESP_LOGV(TAG, "\nBegin esp_mp_mulmod \n"); -#ifdef WOLFSSL_HW_METRICS - esp_mp_max_used = (X->used > esp_mp_max_used) ? X->used : esp_mp_max_used; - esp_mp_max_used = (Y->used > esp_mp_max_used) ? Y->used : esp_mp_max_used; - esp_mp_max_used = (M->used > esp_mp_max_used) ? M->used : esp_mp_max_used; -#endif - /* do we have an even moduli? */ if ((M->dp[0] & 1) == 0) { #ifndef NO_ESP_MP_MUL_EVEN_ALT_CALC @@ -1416,8 +1856,6 @@ int esp_mp_mulmod(MATH_INT_T* X, MATH_INT_T* Y, MATH_INT_T* M, MATH_INT_T* Z) } #endif - - #ifdef DEBUG_WOLFSSL if (IS_HW_VALIDATION) { ESP_LOGE(TAG, "Caller must not try HW when validation active."); @@ -1434,13 +1872,13 @@ int esp_mp_mulmod(MATH_INT_T* X, MATH_INT_T* Y, MATH_INT_T* M, MATH_INT_T* Z) mp_copy(M, M2); /* copy (src = M) to (dst = M2) */ mp_copy(Z, Z2); /* copy (src = Z) to (dst = Z2) */ - SET_HW_VALIDATION; + SET_HW_VALIDATION; /* for the next mulmod to be SW for HW validation */ reti = mp_mulmod(X2, Y2, M2, Z2); if (reti == 0) { - ESP_LOGV(TAG, "wolfSSL mp_mulmod during vaidation success"); + ESP_LOGV(TAG, "wolfSSL mp_mulmod during validation success"); } else { - ESP_LOGE(TAG, "wolfSSL mp_mulmod during vaidation failed"); + ESP_LOGE(TAG, "wolfSSL mp_mulmod during validation failed"); } CLR_HW_VALIDATION; } @@ -1449,9 +1887,9 @@ int esp_mp_mulmod(MATH_INT_T* X, MATH_INT_T* Y, MATH_INT_T* M, MATH_INT_T* Z) if (ret == MP_OKAY) { /* neg check: X*Y becomes negative, we'll need adjustment */ -#if defined(WOLFSSL_SP_INT_NEGATIVE) || defined(USE_FAST_MATH) + #if defined(WOLFSSL_SP_INT_NEGATIVE) || defined(USE_FAST_MATH) negcheck = mp_isneg(X) != mp_isneg(Y) ? 1 : 0; -#endif + #endif /* calculate r_inv = R^2 mod M * where: R = b^n, and b = 2^32 @@ -1462,7 +1900,7 @@ int esp_mp_mulmod(MATH_INT_T* X, MATH_INT_T* Y, MATH_INT_T* M, MATH_INT_T* Z) ESP_LOGV(TAG, "esp_mp_exptmod esp_mp_montgomery_init success."); } else { - #ifdef WOLFSSL_HW_METRICS + #ifdef WOLFSSL_HW_METRICS if (ret == MP_HW_FALLBACK) { esp_mp_mulmod_fallback_ct++; } @@ -1475,8 +1913,37 @@ int esp_mp_mulmod(MATH_INT_T* X, MATH_INT_T* Y, MATH_INT_T* M, MATH_INT_T* Z) zwords = bits2words(min(mph->Ms, mph->Xs + mph->Ys)); } + /* we'll use hardware only for a minimum number of bits */ + if (mph->Xs <= ESP_RSA_MULM_BITS || mph->Ys <= ESP_RSA_MULM_BITS) { + #ifdef WOLFSSL_HW_METRICS + { + esp_mp_mulmod_small_y_ct++; /* track how many times we fall back */ + } + #endif + ret = MP_HW_FALLBACK; + /* TODO add debug metrics */ + #ifdef WOLFSSL_DEBUG_ESP_RSA_MULM_BITS + { + ESP_LOGV(TAG, "esp_mp_mulmod falling back for ESP_RSA_MULM_BITS!"); + } + #endif + } + /* lock HW for use, enable peripheral clock */ if (ret == MP_OKAY) { + mulmod_lock_called = TRUE; /* Don't try to unlock unless we locked */ + #ifdef WOLFSSL_HW_METRICS + { + /* Only track max values when using HW */ + esp_mp_max_used = (X->used > esp_mp_max_used) ? X->used : + esp_mp_max_used; + esp_mp_max_used = (Y->used > esp_mp_max_used) ? Y->used : + esp_mp_max_used; + esp_mp_max_used = (M->used > esp_mp_max_used) ? M->used : + esp_mp_max_used; + } + #endif + ret = esp_mp_hw_lock(); } @@ -1529,8 +1996,8 @@ int esp_mp_mulmod(MATH_INT_T* X, MATH_INT_T* Y, MATH_INT_T* M, MATH_INT_T* Z) /* step.2 write X, M, and r_inv into memory. * The capacity of each memory block is 128 words. - * The memory blocks use the little endian format for storage, - * i.e. the least significant digit of each number is in lowest address.*/ + * The memory blocks use the little endian format for storage, i.e. + * the least significant digit of each number is in lowest address.*/ esp_mpint_to_memblock(RSA_MEM_X_BLOCK_BASE, X, mph->Xs, mph->hwWords_sz); esp_mpint_to_memblock(RSA_MEM_M_BLOCK_BASE, @@ -1552,9 +2019,11 @@ int esp_mp_mulmod(MATH_INT_T* X, MATH_INT_T* Y, MATH_INT_T* M, MATH_INT_T* Z) wait_until_done(RSA_INTERRUPT_REG); /* step.7 Y to MEM_X */ - esp_mpint_to_memblock(RSA_MEM_X_BLOCK_BASE, Y, mph->Ys, mph->hwWords_sz); - -#ifdef DEBUG_WOLFSSL + esp_mpint_to_memblock(RSA_MEM_X_BLOCK_BASE, + Y, mph->Ys, + mph->hwWords_sz); + +#ifdef DEBUG_WOLFSSL /* save value to peek at the result stored in RSA_MEM_Z_BLOCK_BASE */ esp_memblock_to_mpint(RSA_MEM_X_BLOCK_BASE, PEEK, @@ -1573,22 +2042,212 @@ int esp_mp_mulmod(MATH_INT_T* X, MATH_INT_T* Y, MATH_INT_T* M, MATH_INT_T* Z) } /* step 1 .. 12 */ /* step.13 clear and release HW */ - esp_mp_hw_unlock(); + if (mulmod_lock_called) { + ret = esp_mp_hw_unlock(); + } + else { + ESP_LOGV(TAG, "Lock not called"); + } + /* end of ESP32 */ -#elif defined(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. +#elif defined(CONFIG_IDF_TARGET_ESP32C3) + /* Steps to perform large number modular multiplication. + * 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. + * We must use the same number of words to represent bits in X, Y and M. + * See 20.3.3 of ESP32-C3 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 == MP_OKAY) { + ret = esp_mp_hw_wait_clean(); + } + + if (ret == MP_OKAY) { + /* 2. Disable completion interrupt signal; we don't use. + ** 0 => no interrupt; 1 => interrupt on completion. */ + DPORT_REG_WRITE(RSA_INTERRUPT_REG, 0); + + /* 3. Write (N_result_bits/32 - 1) to the RSA_MODE_REG. */ + OperandBits = max(max(mph->Xs, mph->Ys), mph->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); + /* alt inline calc: + * DPORT_REG_WRITE(RSA_MULT_MODE_REG, (mph->hwWords_sz >> 4) - 1); */ + 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, mph->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, + mph->Xs, + mph->hwWords_sz); + esp_mpint_to_memblock(RSA_MEM_Y_BLOCK_BASE, + Y, + mph->Ys, + mph->hwWords_sz); + esp_mpint_to_memblock(RSA_MEM_M_BLOCK_BASE, + M, + mph->Ms, + mph->hwWords_sz); + esp_mpint_to_memblock(RSA_MEM_RB_BLOCK_BASE, + &(mph->r_inv), + mph->Rs, + mph->hwWords_sz); + + /* 6. Start operation and wait until it completes. */ + process_start(RSA_MOD_MULT_START_REG); /* esp_mp_mulmod */ + } + + if (ret == MP_OKAY) { + ret = wait_until_done(RSA_QUERY_INTERRUPT_REG); + } + + if (ret == MP_OKAY) { + /* 7. read the result from MEM_Z */ + esp_memblock_to_mpint(RSA_MEM_Z_BLOCK_BASE, tmpZ, zwords); + } + + /* 8. clear and release HW */ + if (mulmod_lock_called) { + ret = esp_mp_hw_unlock(); + } + else { + ESP_LOGV(TAG, "Lock not called, esp_mp_hw_unlock skipped"); + } + /* end if CONFIG_IDF_TARGET_ESP32C3 */ + +#elif defined(CONFIG_IDF_TARGET_ESP32C6) + /* Steps to perform large number modular multiplication. + * 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 X and Y is 2048. + * We must use the same number of words to represent the bits 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. + * 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). + * 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 for esp_mp_mulmod. */ + if (ret == MP_OKAY) { + ret = esp_mp_hw_wait_clean(); + } + if (ret == MP_OKAY) { + /* 2. Disable completion interrupt signal; we don't use. + ** 0 => no interrupt; 1 => interrupt on completion. */ + DPORT_REG_WRITE(RSA_INT_ENA_REG, 0); + + /* 3. Write (N_result_bits/32 - 1) to the RSA_MODE_REG. */ + OperandBits = max(max(mph->Xs, mph->Ys), mph->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); + /* alt inline calc: + * DPORT_REG_WRITE(RSA_MULT_MODE_REG, (mph->hwWords_sz >> 4) - 1); */ + DPORT_REG_WRITE(RSA_MODE_REG, WordsForOperand - 1); + + /* 4. Write M' value into RSA_M_PRIME_REG + * (now called RSA_M_DASH_REG) */ + DPORT_REG_WRITE(RSA_M_PRIME_REG, mph->mp); + + /* Select acceleration options. */ + DPORT_REG_WRITE(RSA_CONSTANT_TIME_REG, 0); + DPORT_REG_WRITE(RSA_SEARCH_POS_REG, 0); /* or RSA_SEARCH_ENABLE */ + + /* 5. Load X, Y, M, r' operands. + * Note RSA_MEM_RB_BLOCK_BASE == RSA_M_MEM on ESP32-C6*/ + esp_mpint_to_memblock(RSA_X_MEM, + X, + mph->Xs, + mph->hwWords_sz); + esp_mpint_to_memblock(RSA_Y_MEM, + Y, + mph->Ys, + mph->hwWords_sz); + esp_mpint_to_memblock(RSA_M_MEM, + M, + mph->Ms, + mph->hwWords_sz); + esp_mpint_to_memblock(RSA_Z_MEM, + &(mph->r_inv), + mph->Rs, + mph->hwWords_sz); + + /* 6. Start operation and wait until it completes. */ + process_start(RSA_SET_START_MODMULT_REG); /* reminder: esp_mp_mulmod */ + } + + /* 5. Wait for the completion of computation, which happens when the + * content of RSA_QUERY_IDLE becomes 1 or the RSA interrupt occurs. */ + if (ret == MP_OKAY) { + ret = wait_until_done(RSA_QUERY_IDLE_REG); + } + if (ret == MP_OKAY) { + /* 7. read the result from MEM_Z */ + esp_memblock_to_mpint(RSA_Z_MEM, tmpZ, zwords); + } + + /* 8. clear and release HW */ + if (mulmod_lock_called) { + ret = esp_mp_hw_unlock(); + } + else { + ESP_LOGV(TAG, "Lock not called, esp_mp_hw_unlock skipped"); + } + + /* end if CONFIG_IDF_TARGET_ESP32C3 or CONFIG_IDF_TARGET_ESP32C6 */ +#elif defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3) + /* Steps to perform large number modular multiplication. + * 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. + * We must use the same number of words to represent 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). */ @@ -1610,9 +2269,12 @@ int esp_mp_mulmod(MATH_INT_T* X, MATH_INT_T* Y, MATH_INT_T* M, MATH_INT_T* Z) return MP_VAL; /* Error: value is not able to be used. */ } WordsForOperand = bits2words(OperandBits); + /* alt inline calc: + * DPORT_REG_WRITE(RSA_MULT_MODE_REG, (mph->hwWords_sz >> 4) - 1); */ DPORT_REG_WRITE(RSA_LENGTH_REG, WordsForOperand - 1); - /* 4. Write M' value into RSA_M_PRIME_REG (now called RSA_M_DASH_REG) */ + /* 4. Write M' value into RSA_M_PRIME_REG + * (now called RSA_M_DASH_REG) */ DPORT_REG_WRITE(RSA_M_DASH_REG, mph->mp); /* Select acceleration options. */ @@ -1638,7 +2300,7 @@ int esp_mp_mulmod(MATH_INT_T* X, MATH_INT_T* Y, MATH_INT_T* M, MATH_INT_T* Z) mph->hwWords_sz); /* 6. Start operation and wait until it completes. */ - process_start(RSA_MOD_MULT_START_REG); /* we're here in esp_mp_mulmod */ + process_start(RSA_MOD_MULT_START_REG); /* Reminder: esp_mp_mulmod() */ asm volatile("memw"); asm volatile("nop"); asm volatile("nop"); @@ -1658,13 +2320,24 @@ int esp_mp_mulmod(MATH_INT_T* X, MATH_INT_T* Y, MATH_INT_T* M, MATH_INT_T* Z) } /* 8. clear and release HW */ - esp_mp_hw_unlock(); + if (mulmod_lock_called) { + ret = esp_mp_hw_unlock(); + } + else { + if (ret == MP_HW_FALLBACK) { + ESP_LOGV(TAG, "Lock not called due to no-lock MP_HW_FALLBACK"); + } + else { + ESP_LOGW(TAG, "Lock unexpectedly not called"); + } + } /* end if CONFIG_IDF_TARGET_ESP32S3 */ #else /* for all non-supported chipsets, fall back to SW calcs */ ret = MP_HW_FALLBACK; #endif + if (ret == MP_OKAY) { /* additional steps */ /* this is needed for known issue when Z is greater than M */ @@ -1723,6 +2396,16 @@ int esp_mp_mulmod(MATH_INT_T* X, MATH_INT_T* Y, MATH_INT_T* M, MATH_INT_T* Z) esp_show_mp("Y", Y2); esp_show_mp("M", M2); + ESP_LOGI(TAG, "Xs = %d", mph->Xs); + ESP_LOGI(TAG, "Ys = %d", mph->Ys); + ESP_LOGI(TAG, "found_z_used = %d", found_z_used); + ESP_LOGI(TAG, "z.used = %d", Z->used); + ESP_LOGI(TAG, "hwWords_sz = %d", mph->hwWords_sz); + ESP_LOGI(TAG, "maxWords_sz = %d", mph->maxWords_sz); + ESP_LOGI(TAG, "hwWords_sz<<2 = %d", mph->hwWords_sz << 2); + esp_show_mp("X", X2); /* X2 copy, as X may have been clobbered */ + esp_show_mp("Y", Y2); /* Y2 copy, as Y may have been clobbered */ + esp_show_mp("M", M2); /* M2 copy, as M may have been clobbered */ esp_show_mp("r_inv", &(mph->r_inv)); /*show r_inv */ ESP_LOGI(TAG, "mp = 0x%08x = %u", mph->mp, mph->mp); @@ -1743,6 +2426,13 @@ int esp_mp_mulmod(MATH_INT_T* X, MATH_INT_T* Y, MATH_INT_T* M, MATH_INT_T* Z) } + esp_show_mp("HW Z", Z); /* this is the HW result */ + esp_show_mp("SW Z2", Z2); /* this is the SW result */ + ESP_LOGI(TAG, "esp_mp_mulmod_usage_ct = %lu tries", + esp_mp_mulmod_usage_ct); + ESP_LOGI(TAG, "esp_mp_mulmod_error_ct = %lu failures", + esp_mp_mulmod_error_ct); + ESP_LOGI(TAG, ""); esp_show_mp("HW Z", Z); /* this is the HW result */ esp_show_mp("SW Z2", Z2); /* this is the SW result */ ESP_LOGI(TAG, "esp_mp_mulmod_usage_ct = %lu tries", @@ -1753,10 +2443,15 @@ int esp_mp_mulmod(MATH_INT_T* X, MATH_INT_T* Y, MATH_INT_T* M, MATH_INT_T* Z) #ifndef NO_RECOVER_SOFTWARE_CALC - ESP_LOGW(TAG, "Recovering mp_mul error with software result"); - mp_copy(Z2, Z); /* copy (src = Z2) to (dst = Z) */ + { + ESP_LOGW(TAG, "Recovering mp_mul error with software result"); + mp_copy(Z2, Z); /* copy (src = Z2) to (dst = Z) */ + } #else - ret = MP_VAL; /* if we are not recovering, then we have an error */ + { + /* If we are not recovering, then we have an error. */ + ret = MP_VAL; + } #endif } else { @@ -1771,7 +2466,7 @@ int esp_mp_mulmod(MATH_INT_T* X, MATH_INT_T* Y, MATH_INT_T* M, MATH_INT_T* Z) mp_clear(&(mph->r_inv)); ESP_LOGV(TAG, "\nEnd esp_mp_mulmod \n"); - if (ret == MP_OKAY) { + if (ret == MP_OKAY || ret == MP_HW_FALLBACK) { ESP_LOGV(TAG, "esp_mp_mulmod exit success "); } else { @@ -1784,7 +2479,7 @@ int esp_mp_mulmod(MATH_INT_T* X, MATH_INT_T* Y, MATH_INT_T* M, MATH_INT_T* Z) #endif return ret; } /* esp_mp_mulmod */ -#endif /* ! NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_MULMOD */ +#endif /* Use HW mulmod: ! NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_MULMOD */ #ifndef NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_EXPTMOD @@ -1800,9 +2495,10 @@ int esp_mp_mulmod(MATH_INT_T* X, MATH_INT_T* Y, MATH_INT_T* M, MATH_INT_T* Z) .* 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 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. +.* 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. .* * Z = (X ^ Y) mod M : Espressif generic notation @@ -1815,12 +2511,18 @@ int esp_mp_exptmod(MATH_INT_T* X, MATH_INT_T* Y, MATH_INT_T* M, MATH_INT_T* Z) * (e.g. the address of X and Z could be the same when called) */ struct esp_mp_helper mph[1]; /* we'll save some mp helper data here */ int ret = MP_OKAY; + int exptmod_lock_called = FALSE; #if defined(CONFIG_IDF_TARGET_ESP32) -#elif defined(CONFIG_IDF_TARGET_ESP32S3) - uint32_t OperandBits; - uint32_t WordsForOperand; + /* different calc */ +#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) + word32 OperandBits; + word32 WordsForOperand; +#elif defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3) + word32 OperandBits; + word32 WordsForOperand; #else + /* no HW */ #endif ESP_LOGV(TAG, "\nBegin esp_mp_exptmod \n"); @@ -1886,14 +2588,25 @@ int esp_mp_exptmod(MATH_INT_T* X, MATH_INT_T* Y, MATH_INT_T* M, MATH_INT_T* Z) /* lock and init the HW */ if (ret == MP_OKAY) { + exptmod_lock_called = TRUE; /* Don't try to unlock unless we locked */ + #ifdef WOLFSSL_HW_METRICS + { + /* Only track max values when using HW */ + esp_mp_max_used = (X->used > esp_mp_max_used) ? X->used : + esp_mp_max_used; + esp_mp_max_used = (Y->used > esp_mp_max_used) ? Y->used : + esp_mp_max_used; + } + #endif + ret = esp_mp_hw_lock(); if (ret != MP_OKAY) { ESP_LOGE(TAG, "esp_mp_hw_lock failed"); - #ifdef DEBUG_WOLFSSL - esp_mp_exptmod_depth_counter--; - #endif + #ifdef DEBUG_WOLFSSL + esp_mp_exptmod_depth_counter--; + #endif } - } + } /* the only thing we expect is success or busy */ #if defined(CONFIG_IDF_TARGET_ESP32) /* non-ESP32S3 Xtensa (regular ESP32) */ @@ -1960,22 +2673,204 @@ int esp_mp_exptmod(MATH_INT_T* X, MATH_INT_T* Y, MATH_INT_T* M, MATH_INT_T* Z) esp_memblock_to_mpint(RSA_MEM_Z_BLOCK_BASE, Z, BITS_TO_WORDS(mph->Ms)); } - /* step.7 clear and release HW */ - esp_mp_hw_unlock(); + /* step.7 clear and release expt_mod HW */ + if (exptmod_lock_called) { + ret = esp_mp_hw_unlock(); + } + else { + ESP_LOGV(TAG, "Lock not called"); + } -#elif defined(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. +#elif defined(CONFIG_IDF_TARGET_ESP32C3) + /* 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}; 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 == MP_OKAY) { + ret = esp_mp_hw_wait_clean(); + } + + if (ret == MP_OKAY) { + OperandBits = max(max(mph->Xs, mph->Ys), mph->Ms); + if (OperandBits > ESP_HW_MULTI_RSAMAX_BITS) { + ESP_LOGW(TAG, "result exceeds max bit length"); + ret = MP_VAL; /* Error: value is not able to be used. */ + } + else { + WordsForOperand = bits2words(OperandBits); + } + } + + if (ret == MP_OKAY) { + /* 2. Disable completion interrupt signal; we don't use. + ** 0 => no interrupt; 1 => interrupt on completion. */ + DPORT_REG_WRITE(RSA_INTERRUPT_REG, 0); + + /* 3. Write (N_result_bits/32 - 1) to the RSA_MODE_REG. */ + 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, mph->mp); + + /* 5. Load X, Y, M, r' operands. */ + esp_mpint_to_memblock(RSA_MEM_X_BLOCK_BASE, + X, + mph->Xs, + mph->hwWords_sz); + esp_mpint_to_memblock(RSA_MEM_Y_BLOCK_BASE, + Y, + mph->Ys, + mph->hwWords_sz); + esp_mpint_to_memblock(RSA_MEM_M_BLOCK_BASE, + M, + mph->Ms, + mph->hwWords_sz); + esp_mpint_to_memblock(RSA_MEM_Z_BLOCK_BASE, + &(mph->r_inv), + mph->Rs, + mph->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) { + /* 7. read the result form MEM_Z */ + esp_memblock_to_mpint(RSA_MEM_Z_BLOCK_BASE, Z, BITS_TO_WORDS(mph->Ms)); + } + + /* 8. clear and release HW */ + if (exptmod_lock_called) { + ret = esp_mp_hw_unlock(); + } + else { + ESP_LOGV(TAG, "Lock not called"); + } + /* end if CONFIG_IDF_TARGET_ESP32C3 */ + +#elif defined(CONFIG_IDF_TARGET_ESP32C6) + /* 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}; 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). + * 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 == MP_OKAY) { + ret = esp_mp_hw_wait_clean(); + } + + if (ret == MP_OKAY) { + OperandBits = max(max(mph->Xs, mph->Ys), mph->Ms); + if (OperandBits > ESP_HW_MULTI_RSAMAX_BITS) { + ESP_LOGW(TAG, "result exceeds max bit length"); + ret = MP_VAL; /* Error: value is not able to be used. */ + } + else { + WordsForOperand = bits2words(OperandBits); + } + } + + if (ret == MP_OKAY) { + /* 2. Disable completion interrupt signal; we don't use. + ** 0 => no interrupt; 1 => interrupt on completion. */ + DPORT_REG_WRITE(RSA_INT_ENA_REG, 0); + + /* 3. Write (N_result_bits/32 - 1) to the RSA_MODE_REG. */ + DPORT_REG_WRITE(RSA_MODE_REG, WordsForOperand - 1); + + /* 4. Write M' value into RSA_M_PRIME_REG */ + DPORT_REG_WRITE(RSA_M_PRIME_REG, mph->mp); + + /* 5. Load X, Y, M, r' operands. */ + esp_mpint_to_memblock(RSA_X_MEM, + X, + mph->Xs, + mph->hwWords_sz); + esp_mpint_to_memblock(RSA_Y_MEM, + Y, + mph->Ys, + mph->hwWords_sz); + esp_mpint_to_memblock(RSA_M_MEM, + M, + mph->Ms, + mph->hwWords_sz); + esp_mpint_to_memblock(RSA_Z_MEM, + &(mph->r_inv), + mph->Rs, + mph->hwWords_sz); + + /* 6. Start operation and wait until it completes. */ + /* Write 1 to the RSA_SET_START_MODEXP field of the + * RSA_SET_START_MODEXP_REG register to start computation.*/ + process_start(RSA_SET_START_MODEXP_REG); + ret = wait_until_done(RSA_QUERY_IDLE_REG); + } + + if (MP_OKAY == ret) { + /* 7. read the result form MEM_Z */ + esp_memblock_to_mpint(RSA_Z_MEM, Z, BITS_TO_WORDS(mph->Ms)); + } + + /* 8. clear and release HW */ + if (exptmod_lock_called) { + ret = esp_mp_hw_unlock(); + } + else { + ESP_LOGV(TAG, "Lock not called"); + } + /* end if CONFIG_IDF_TARGET_ESP32C6 */ + +#elif defined(CONFIG_IDF_TARGET_ESP32S2) || defined(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}; the maximum number of bits in 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). + * 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). */ @@ -2004,7 +2899,8 @@ int esp_mp_exptmod(MATH_INT_T* X, MATH_INT_T* Y, MATH_INT_T* M, MATH_INT_T* Z) /* 3. Write (N_result_bits/32 - 1) to the RSA_MODE_REG. */ DPORT_REG_WRITE(RSA_LENGTH_REG, WordsForOperand - 1); - /* 4. Write M' value into RSA_M_PRIME_REG (now called RSA_M_DASH_REG) */ + /* 4. Write M' value into RSA_M_PRIME_REG + * (now called RSA_M_DASH_REG) */ DPORT_REG_WRITE(RSA_M_DASH_REG, mph->mp); /* 5. Load X, Y, M, r' operands. */ @@ -2036,7 +2932,12 @@ int esp_mp_exptmod(MATH_INT_T* X, MATH_INT_T* Y, MATH_INT_T* M, MATH_INT_T* Z) } /* 8. clear and release HW */ - esp_mp_hw_unlock(); + if (exptmod_lock_called) { + ret = esp_mp_hw_unlock(); + } + else { + ESP_LOGV(TAG, "Lock not called"); + } /* end if CONFIG_IDF_TARGET_ESP32S3 */ #else @@ -2062,22 +2963,27 @@ int esp_mp_exptmod(MATH_INT_T* X, MATH_INT_T* Y, MATH_INT_T* M, MATH_INT_T* Z) return ret; } /* esp_mp_exptmod */ -#endif /* ! NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_EXPTMOD - * (turns on/off mp_exptmod) */ +#endif /* Use HW expmod: ! NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_EXPTMOD */ #endif /* WOLFSSL_ESP32_CRYPT_RSA_PRI) && * !NO_WOLFSSL_ESP32_CRYPT_RSA_PRI */ #endif /* !NO_RSA || HAVE_ECC */ -#ifdef WOLFSSL_HW_METRICS +#if defined(WOLFSSL_ESP32_CRYPT_RSA_PRI) && defined(WOLFSSL_HW_METRICS) int esp_hw_show_mp_metrics(void) { int ret; -#ifdef HW_MATH_ENABLED +#if !defined(NO_ESP32_CRYPT) && defined(HW_MATH_ENABLED) ret = MP_OKAY; +#if defined(NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_MP_MUL) + ESP_LOGI(TAG, "esp_mp_mul HW disabled with " + "NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_MP_MUL"); +#else /* Metrics: esp_mp_mul() */ + ESP_LOGI(TAG, ""); /* mul follows */ + ESP_LOGI(TAG, "esp_mp_mul HW acceleration enabled."); ESP_LOGI(TAG, "Number of calls to esp_mp_mul: %lu", esp_mp_mul_usage_ct); if (esp_mp_mul_error_ct == 0) { @@ -2088,9 +2994,16 @@ int esp_hw_show_mp_metrics(void) esp_mp_mul_error_ct); ret = MP_VAL; } +#endif +#if defined(NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_MULMOD) + ESP_LOGI(TAG, "esp_mp_mulmod HW disabled with " + "NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_MULMOD"); +#else + /* Metrics: esp_mp_mulmod() */ ESP_LOGI(TAG, ""); /* mulmod follows */ + ESP_LOGI(TAG, "esp_mp_mulmod HW acceleration enabled."); /* Metrics: esp_mp_mulmod() */ ESP_LOGI(TAG, "Number of calls to esp_mp_mulmod: %lu", esp_mp_mulmod_usage_ct); @@ -2123,7 +3036,13 @@ int esp_hw_show_mp_metrics(void) ESP_LOGW(TAG, "Number of esp_mp_mulmod small y: %lu", esp_mp_mulmod_small_y_ct); } +#endif /* MULMOD disabled: !NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_MULMOD */ +#if defined(NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_EXPTMOD) + ESP_LOGI(TAG, "esp_mp_exptmod HW disabled with " + "NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_EXPTMOD"); +#else + /* Metrics: sp_mp_exptmod() */ ESP_LOGI(TAG, ""); /* exptmod follows */ ESP_LOGI(TAG, "Number of calls to esp_mp_exptmod: %lu", @@ -2138,11 +3057,17 @@ int esp_hw_show_mp_metrics(void) esp_mp_exptmod_error_ct); ret = MP_VAL; } +#endif /* EXPTMOD not disabled !NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_EXPTMOD */ + ESP_LOGI(TAG, "Max N->used: esp_mp_max_used = %lu", esp_mp_max_used); #else /* no HW math, no HW math metrics */ - ret = 0; + ret = ESP_OK; #endif /* HW_MATH_ENABLED */ + + return ret; } -#endif +#endif /* WOLFSSL_HW_METRICS */ + +#endif /* WOLFSSL_ESPIDF */ diff --git a/wolfcrypt/src/port/Espressif/esp32_sha.c b/wolfcrypt/src/port/Espressif/esp32_sha.c index fc0bc868f3..99a7ffb71f 100644 --- a/wolfcrypt/src/port/Espressif/esp32_sha.c +++ b/wolfcrypt/src/port/Espressif/esp32_sha.c @@ -18,11 +18,24 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ + +/* + * ESP32-C3: https://www.espressif.com/sites/default/files/documentation/esp32-c3_technical_reference_manual_en.pdf + * see page 335: no SHA-512 + * + */ #ifdef HAVE_CONFIG_H #include #endif +/* Reminder: user_settings.h is needed and included from settings.h + * Be sure to define WOLFSSL_USER_SETTINGS, typically in CMakeLists.txt */ #include + +#if defined(WOLFSSL_ESPIDF) /* Entire file is only for Espressif EDP-IDF */ +#include "sdkconfig.h" /* programmatically generated from sdkconfig */ +#include + /*****************************************************************************/ /* this entire file content is excluded when NO_SHA, NO_SHA256 * or when using WC_SHA384 or WC_SHA512 @@ -37,9 +50,14 @@ #if defined(WOLFSSL_ESP32_CRYPT) && \ !defined(NO_WOLFSSL_ESP32_CRYPT_HASH) -/* TODO this may be chip type dependent: add support for others */ -#include /* ESP32-WROOM */ +#if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) + #include + #include + #include +#else + #include /* ESP32-WROOM */ +#endif #include #include #include @@ -54,12 +72,22 @@ #include #endif +#if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) + /* keep track of the currently active SHA hash object for interleaving */ + const static word32 ** _active_digest_address = 0; +#endif + static const char* TAG = "wolf_hw_sha"; #ifdef NO_SHA #define WC_SHA_DIGEST_SIZE 20 #endif +#if defined(DEBUG_WOLFSSL) + /* Only when debugging, we'll keep tracking of block numbers. */ + static int this_block_num = 0; +#endif + /* RTOS mutex or just InUse variable */ #if defined(SINGLE_THREADED) static int InUse = 0; @@ -67,10 +95,108 @@ static const char* TAG = "wolf_hw_sha"; static wolfSSL_Mutex sha_mutex = NULL; #endif -#if defined(DEBUG_WOLFSSL) - /* Only when debugging, we'll keep tracking of block numbers. */ - static int this_block_num = 0; +#ifdef DEBUG_WOLFSSL_SHA_MUTEX + #ifndef WOLFSSL_TEST_STRAY + /* unless turned on, we won't be testing for strays */ + #define WOLFSSL_TEST_STRAY 0 + #endif +#endif + +/* usage metrics can be turned on independently of debugging */ +#ifdef WOLFSSL_HW_METRICS + static unsigned long esp_sha_hw_copy_ct = 0; + static unsigned long esp_sha1_hw_usage_ct = 0; + static unsigned long esp_sha1_sw_fallback_usage_ct = 0; + static unsigned long esp_sha_reverse_words_ct = 0; + static unsigned long esp_sha1_hw_hash_usage_ct = 0; + static unsigned long esp_sha2_224_hw_hash_usage_ct = 0; + static unsigned long esp_sha2_256_hw_hash_usage_ct = 0; + static unsigned long esp_sha256_sw_fallback_usage_ct = 0; + static unsigned long esp_byte_reversal_checks_ct = 0; + static unsigned long esp_byte_reversal_needed_ct = 0; +#endif + +#if defined(ESP_MONITOR_HW_TASK_LOCK) + static void * mutex_ctx_owner = 0; + static TaskHandle_t mutex_ctx_task = 0; + #ifdef DEBUG_WOLFSSL_SHA_MUTEX + static portMUX_TYPE sha_crit_sect = portMUX_INITIALIZER_UNLOCKED; + WC_ESP32SHA* stray_ctx; + /* each ctx keeps track of the intializer for HW. when debugging + * we'll have a global variable to indicate which has the lock. */ + static int _sha_lock_count = 0; + static int _sha_call_count = 0; + + int esp_sha_call_count(void) + { + return _sha_call_count; + } + + int esp_sha_lock_count(void) + { + return _sha_lock_count; + } + + void* esp_sha_mutex_ctx_owner(void) + { + void* ret = 0; + taskENTER_CRITICAL(&sha_crit_sect); + { + ret = mutex_ctx_owner; + } + taskEXIT_CRITICAL(&sha_crit_sect); + return ret; + }; + #else + int esp_sha_mutex_ctx_owner(void) + { + return (int)sha_mutex; + } + #endif +#endif + +/* +** The wolfCrypt functions for LITTLE_ENDIAN_ORDER typically +** reverse the byte order. Except when the hardware doesn't expect it. +*/ +int esp_sha_need_byte_reversal(WC_ESP32SHA* ctx) +{ + int ret = 1; /* assume we'll need reversal, look for exceptions */ +#if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) + if (ctx == NULL) { + ESP_LOGE(TAG, " ctx is null"); + /* return true for bad params */ + } + else { + #ifdef WOLFSSL_HW_METRICS + { + esp_byte_reversal_checks_ct++; + } + #endif + if (ctx->mode == ESP32_SHA_HW) { + ESP_LOGV(TAG, " No reversal, ESP32_SHA_HW"); + ret = 0; + } + else { + ret = 1; + ESP_LOGV(TAG, " Need byte reversal, %d", ctx->mode); + /* return true for SW; only HW C3 skips reversal at this time. */ + #ifdef WOLFSSL_HW_METRICS + { + esp_byte_reversal_needed_ct++; + } + #endif + if (ctx->mode == ESP32_SHA_INIT) { + ESP_LOGW(TAG, "esp_sha_need_byte_reversal during init?"); + ESP_LOGW(TAG, "forgot to try HW lock first?"); + } + } + } +#else + /* other platforms always return true */ #endif + return ret; +} /* esp_sha_init ** @@ -87,21 +213,33 @@ int esp_sha_init(WC_ESP32SHA* ctx, enum wc_HashType hash_type) { int ret = 0; -#if defined(CONFIG_IDF_TARGET_ESP32) || defined(CONFIG_IDF_TARGET_ESP32S3) +#if defined(CONFIG_IDF_TARGET_ESP32) || \ + defined(CONFIG_IDF_TARGET_ESP32S2) || 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; + case WC_HASH_TYPE_SHA224: + #if defined(CONFIG_IDF_TARGET_ESP32S2) || \ + defined(CONFIG_IDF_TARGET_ESP32S3) + ctx->sha_type = SHA2_224; /* assign Espressif SHA HW type */ + ret = esp_sha_init_ctx(ctx); + #else + /* Don't call init, always SW as there's no HW. */ + ctx->mode = ESP32_SHA_SW; + #endif + break; + case WC_HASH_TYPE_SHA256: ctx->sha_type = SHA2_256; /* assign Espressif SHA HW type */ ret = esp_sha_init_ctx(ctx); break; - #ifdef CONFIG_IDF_TARGET_ESP32S3 + #if defined(CONFIG_IDF_TARGET_ESP32S2) || \ + defined(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; @@ -138,13 +276,48 @@ int esp_sha_init(WC_ESP32SHA* ctx, enum wc_HashType hash_type) ESP_LOGW(TAG, "Unexpected hash_type in esp_sha_init"); break; } +#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) + switch (hash_type) { /* check each wolfSSL hash type WC_[n] */ + #ifndef NO_SHA + case WC_HASH_TYPE_SHA: + ctx->sha_type = SHA1; /* assign Espressif SHA HW type */ + ret = esp_sha_init_ctx(ctx); + break; + #endif + + case WC_HASH_TYPE_SHA224: + ctx->sha_type = SHA2_224; /* assign Espressif SHA HW type */ + ret = esp_sha_init_ctx(ctx); + break; + + case WC_HASH_TYPE_SHA256: + ctx->sha_type = SHA2_256; /* assign Espressif SHA HW type */ + ret = esp_sha_init_ctx(ctx); + break; + + default: + /* We fall through to SW when there's no enabled HW, above. */ + ctx->mode = ESP32_SHA_SW; + ret = 0; + /* If there's no HW, the ctx reference should cause build error. + ** The type should be gated away when there's no HW at all! */ + ctx->isfirstblock = true; + ctx->sha_type = hash_type; + ESP_LOGW(TAG, "Unsupported hash_type = %d in esp_sha_init, " + "falling back to SW", hash_type); + break; + } + #else /* other chipsets will be implemented here */ -#endif /* defined(CONFIG_IDF_TARGET_ESP32) || defined(CONFIG_IDF_TARGET_ESP32S3) */ + ESP_LOGW(TAG, "SW Fallback; CONFIG_IDF_TARGET = %s", CONFIG_IDF_TARGET); + ctx->mode = ESP32_SHA_SW; +#endif /* CONFIG_IDF_TARGET_ESP32 || x_ESP32S2 || x_ESP32S3 */ return ret; } +#ifndef NO_SHAx /* TODO cannot currently turn off SHA */ /* we'll call a separate init as there's only 1 HW acceleration */ int esp_sha_init_ctx(WC_ESP32SHA* ctx) { @@ -153,6 +326,12 @@ int esp_sha_init_ctx(WC_ESP32SHA* ctx) /* we'll keep track of who initialized this */ ctx->initializer = ctx; /* save our address in the initializer */ + #ifdef ESP_MONITOR_HW_TASK_LOCK + { + /* Keep track of which freeRTOS task actually locks HW */ + ctx->task_owner = xTaskGetCurrentTaskHandle(); + } + #endif ctx->mode = ESP32_SHA_INIT; } else { @@ -167,6 +346,22 @@ int esp_sha_init_ctx(WC_ESP32SHA* ctx) /* we should never have an unexpected mode in a known ctx */ switch (ctx->mode) { + case ESP32_SHA_FREED: + ESP_LOGW(TAG, "Warning: ESP32_SHA_FREED status"); + + #ifdef ESP_MONITOR_HW_TASK_LOCK + if (ctx->task_owner == xTaskGetCurrentTaskHandle()) { + esp_sha_hw_unlock(ctx); + } + else { + ESP_LOGW(TAG, "Warning: unable to unlock ctx mutex "); + } + #else + esp_sha_hw_unlock(ctx); + #endif + ctx->mode = ESP32_SHA_INIT; + /* fall through to init */ + case ESP32_SHA_INIT: case ESP32_SHA_SW: /* nothing interesting here */ @@ -182,7 +377,7 @@ int esp_sha_init_ctx(WC_ESP32SHA* ctx) break; default: - /* This should almost occur. We'd need to have an + /* This should almost never 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: " @@ -202,9 +397,20 @@ int esp_sha_init_ctx(WC_ESP32SHA* ctx) ** ** In either case, initialize: */ ctx->initializer = ctx; /* set a new address */ + #ifdef ESP_MONITOR_HW_TASK_LOCK + { + /* not HW mode, so we are not interested in task owner */ + ctx->task_owner = 0; + } + #endif /* Always set to ESP32_SHA_INIT, but give debug info as to why: */ switch (ctx->mode) { + case ESP32_SHA_FREED: + ESP_LOGE(TAG, "ERROR: unexpected ESP32_SHA_FREED"); + ctx->mode = ESP32_SHA_INIT; + break; + case ESP32_SHA_INIT: /* if we are already in init mode, nothing to do. */ break; @@ -226,7 +432,8 @@ int esp_sha_init_ctx(WC_ESP32SHA* ctx) 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."); + ESP_LOGV(TAG, "HW WC_ESP32SHA ctx mode = " + "ESP32_SHA_HW_COPY."); break; default: @@ -257,6 +464,7 @@ int esp_sha_init_ctx(WC_ESP32SHA* ctx) ** If there's a problem, likely some undesired operation ** outside of wolfSSL. */ + /* TODO debug check if HW actually locked; */ esp_sha_hw_unlock(ctx); ctx->mode = ESP32_SHA_INIT; break; @@ -294,7 +502,8 @@ int esp_sha_init_ctx(WC_ESP32SHA* ctx) 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. */ + return ESP_OK; /* Always return success. + * We assume all issues handled, above. */ } /* esp_sha_init_ctx */ /* @@ -306,24 +515,40 @@ int esp_sha_ctx_copy(struct wc_Sha* src, struct wc_Sha* dst) 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"); - + #ifdef WOLFSSL_HW_METRICS + { + esp_sha_hw_copy_ct++; + } + #endif /* 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 */ + /* Note we arrived here only because + * the src is already in HW mode. + * 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_SHA); if (ret != 0) { - ESP_LOGE(TAG, "Error during esp_sha_ctx_copy in esp_sha_init."); + 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."); + ESP_LOGE(TAG, "Error during esp_sha_ctx_copy " + "in esp_sha_digest_process."); } if (dst->ctx.mode == ESP32_SHA_SW) { + #if defined(CONFIG_IDF_TARGET_ESP32C3) || \ + defined(CONFIG_IDF_TARGET_ESP32C6) + /* Reverse digest for C3 when HW enabled but fallback to SW. */ + ByteReverseWords(dst->digest, dst->digest, WC_SHA_DIGEST_SIZE); + #ifdef WOLFSSL_HW_METRICS + esp_sha_reverse_words_ct++; + #endif + #endif /* The normal revert to SW in copy is expected */ ESP_LOGV(TAG, "Confirmed SHA Copy set to SW"); } @@ -339,27 +564,42 @@ int esp_sha_ctx_copy(struct wc_Sha* src, struct wc_Sha* dst) ** 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 */ + #ifdef ESP_MONITOR_HW_TASK_LOCK + { + /* not HW mode for copy, so we are not interested in task owner */ + dst->ctx.task_owner = 0; + } + #endif + ret = 0; } return ret; } /* esp_sha_ctx_copy */ +#endif + /* ** internal sha224 ctx copy (no ESP HW) */ +#ifndef NO_WOLFSSL_ESP32_CRYPT_HASH_SHA224 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 */ + #ifdef ESP_MONITOR_HW_TASK_LOCK + { + /* not HW mode for copy, so we are not interested in task owner */ + dst->ctx.task_owner = 0; + } + #endif - /* 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; + return ESP_OK; } /* esp_sha224_ctx_copy */ +#endif +#ifndef NO_WOLFSSL_ESP32_CRYPT_HASH_SHA256 /* ** internal sha256 ctx copy for ESP HW */ @@ -368,7 +608,11 @@ 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"); + #ifdef DEBUG_WOLFSSL_SHA_MUTEX + { + ESP_LOGI(TAG, "esp_sha256_ctx_copy esp_sha512_digest_process"); + } + #endif ret = esp_sha256_digest_process(dst, 0); if (ret == 0) { @@ -380,6 +624,15 @@ int esp_sha256_ctx_copy(struct wc_Sha256* src, struct wc_Sha256* dst) } if (dst->ctx.mode == ESP32_SHA_SW) { + #if defined(CONFIG_IDF_TARGET_ESP32C3) || \ + defined(CONFIG_IDF_TARGET_ESP32C6) + { + /* Reverse digest byte order for C3 fallback to SW. */ + ByteReverseWords(dst->digest, + dst->digest, + WC_SHA256_DIGEST_SIZE); + } + #endif ESP_LOGV(TAG, "Confirmed wc_Sha256 Copy set to SW"); } else { @@ -393,17 +646,29 @@ int esp_sha256_ctx_copy(struct wc_Sha256* src, struct wc_Sha256* dst) ** 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 */ + #ifdef ESP_MONITOR_HW_TASK_LOCK + { + /* not HW mode, so we are not interested in task owner */ + dst->ctx.task_owner = 0; + } + #endif } /* not (src->ctx.mode == ESP32_SHA_HW) */ return ret; } /* esp_sha256_ctx_copy */ +#endif +#if defined(WOLFSSL_SHA384) || defined(WOLFSSL_SHA512) /* ** internal sha384 ctx copy for ESP HW */ int esp_sha384_ctx_copy(struct wc_Sha512* src, struct wc_Sha512* dst) { - int ret; + int ret = 0; +#if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) + ESP_LOGW(TAG, "Warning: esp_sha384_ctx_copy() called for ESP32-C3!"); + ESP_LOGW(TAG, "There's no SHA384 HW for the ESP32-C3"); +#else 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"); @@ -415,11 +680,13 @@ int esp_sha384_ctx_copy(struct wc_Sha512* src, struct wc_Sha512* dst) /* 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."); + 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."); + ESP_LOGE(TAG, "Error during esp_sha384_ctx_copy " + "in esp_sha512_digest_process."); } /* just some diagnostic runtime info */ @@ -437,18 +704,27 @@ int esp_sha384_ctx_copy(struct wc_Sha512* src, struct wc_Sha512* dst) ** 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 */ + #ifdef ESP_MONITOR_HW_TASK_LOCK + { + /* not HW mode for copy, so we are not interested in task owner */ + dst->ctx.task_owner = 0; + } + #endif } /* not (src->ctx.mode == ESP32_SHA_HW) */ - +#endif return ret; } /* esp_sha384_ctx_copy */ +#endif +#if defined(WOLFSSL_SHA384) || defined(WOLFSSL_SHA512) /* ** 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; + int ret = 0; +#if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C6) 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"); @@ -476,18 +752,28 @@ int esp_sha512_ctx_copy(struct wc_Sha512* src, struct wc_Sha512* dst) /* 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: */ + #if !defined(CONFIG_IDF_TARGET_ESP32C3) && \ + !defined(CONFIG_IDF_TARGET_ESP32C6) dst->ctx.initializer = &dst->ctx; /*breadcrumb is this ctx address */ + #endif + #ifdef ESP_MONITOR_HW_TASK_LOCK + { + /* not HW mode for copy, so we are not interested in task owner */ + dst->ctx.task_owner = 0; + } + #endif } - +#endif return ret; } /* esp_sha512_ctx_copy */ +#endif /* -** determine the digest size, depending on SHA type. +** Determine the digest size, depending on SHA type. ** ** See FIPS PUB 180-4, Instruction Section 1. ** -** see ESP32 shah.h for values: +** See ESP32 shah.h for values: ** ** enum SHA_TYPE { ** SHA1 = 0, @@ -507,40 +793,72 @@ static word32 wc_esp_sha_digest_size(WC_ESP_SHA_TYPE type) int ret = 0; ESP_LOGV(TAG, " esp_sha_digest_size"); +#if CONFIG_IDF_TARGET_ARCH_RISCV +/* + * SHA1 = 0, + * SHA2_224, + * SHA2_256, + */ switch (type) { #ifndef NO_SHA case SHA1: /* typically 20 bytes */ ret = WC_SHA_DIGEST_SIZE; break; -#endif + #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 + #endif + default: + ESP_LOGE(TAG, "Bad SHA type in wc_esp_sha_digest_size"); + ret = 0; + break; + } +#else + /* Xtnsa */ + switch (type) { + #ifndef NO_SHA + case SHA1: /* typically 20 bytes */ + ret = WC_SHA_DIGEST_SIZE; + break; + #endif + + #ifdef WOLFSSL_SHA224 + #if defined(CONFIG_IDF_TARGET_ESP32S2) || \ + defined(CONFIG_IDF_TARGET_ESP32S3) + case SHA2_224: + ret = WC_SHA224_DIGEST_SIZE; + break; + #endif + #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 + #endif #ifdef WOLFSSL_SHA512 case SHA2_512: /* typically 64 bytes */ ret = WC_SHA512_DIGEST_SIZE; break; -#endif + #endif default: ESP_LOGE(TAG, "Bad SHA type in wc_esp_sha_digest_size"); ret = 0; break; } +#endif return ret; /* Return value is a size, not an error code. */ } /* wc_esp_sha_digest_size */ @@ -551,10 +869,15 @@ static word32 wc_esp_sha_digest_size(WC_ESP_SHA_TYPE type) static int wc_esp_wait_until_idle(void) { int ret = 0; /* assume success */ + int loop_ct = 10000; #if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) - /* ESP32-C3 RISC-V TODO */ -#elif defined(CONFIG_IDF_TARGET_ESP32S3) + /* ESP32-C3 and ESP32-C6 RISC-V */ + while ((sha_ll_busy() == true) && (loop_ct > 0)) { + loop_ct--; + /* do nothing while waiting. */ + } +#elif defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3) while (REG_READ(SHA_BUSY_REG)) { /* do nothing while waiting. */ } @@ -566,7 +889,10 @@ static int wc_esp_wait_until_idle(void) /* do nothing while waiting. */ } #endif - + if (loop_ct <= 0) + { + ESP_LOGI(TAG, "too long to exit wc_esp_wait_until_idle"); + } return ret; } /* wc_esp_wait_until_idle */ @@ -581,8 +907,6 @@ static int wc_esp_wait_until_idle(void) ** ** 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) { @@ -593,7 +917,7 @@ int esp_unroll_sha_module_enable(WC_ESP32SHA* ctx) int max_unroll_count = 1000; /* never get stuck in a hardware wait loop */ #if defined(CONFIG_IDF_TARGET_ESP32) - uint32_t this_sha_mask; /* this is the bit-mask for our SHA CLK_EN_REG */ + word32 this_sha_mask; /* this is the bit-mask for our SHA CLK_EN_REG */ #endif if (ctx == NULL) { @@ -602,7 +926,10 @@ int esp_unroll_sha_module_enable(WC_ESP32SHA* ctx) } #if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) - /* RISC-V Architecture: TODO */ + /* RISC-V Architecture */ + (void)max_unroll_count; + (void)_active_digest_address; + ets_sha_disable(); #else /* Xtensa Architecture */ @@ -611,7 +938,7 @@ int esp_unroll_sha_module_enable(WC_ESP32SHA* ctx) /* 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 +#if defined(CONFIG_IDF_TARGET_ESP32S2) ||defined(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)) { @@ -630,7 +957,7 @@ int esp_unroll_sha_module_enable(WC_ESP32SHA* ctx) /* we'll only try this some unreasonable number of times * before giving up */ if (actual_unroll_count > max_unroll_count) { - ret = -1; /* failed to unroll */ + ret = ESP_FAIL; /* failed to unroll */ break; } } @@ -660,6 +987,116 @@ int esp_unroll_sha_module_enable(WC_ESP32SHA* ctx) return ret; } /* esp_unroll_sha_module_enable */ +int esp_sha_set_stray(WC_ESP32SHA* ctx) +{ + int ret = 0; +#ifdef DEBUG_WOLFSSL_SHA_MUTEX + stray_ctx = ctx; + ret= (int)stray_ctx; +#endif + return ret; +} + +/* +** return HW lock owner, otherwise zero if not locked. +** +** When DEBUG_WOLFSSL_SHA_MUTEX is defined, additional +** debugging capabilities are available. +*/ +int esp_sha_hw_islocked(WC_ESP32SHA* ctx) +{ + int ret = 0; +#ifdef DEBUG_WOLFSSL_SHA_MUTEX + taskENTER_CRITICAL(&sha_crit_sect); + { + ret = (int)mutex_ctx_owner; + if (ctx == 0) { + /* we are not checking if a given ctx has the lock */ + } + else { + if (ret == (int)ctx->initializer) { + /* confirmed this object is the owner */ + } + else { + /* this object is not the lock owner */ + } + } + } + taskEXIT_CRITICAL(&sha_crit_sect); +#else + #ifdef SINGLE_THREADED + { + ret = InUse; + } + #else + { + ret = (int)sha_mutex; + } + #endif + return ret; +#endif + + +#ifdef DEBUG_WOLFSSL_SHA_MUTEX + if (ret == 0) { + ESP_LOGV(TAG, ">> NOT LOCKED esp_sha_hw_islocked"); + } + else { + ESP_LOGV(TAG, ">> LOCKED esp_sha_hw_islocked for %x", + (int)esp_sha_mutex_ctx_owner()); + } +#endif + return ret; +} + +/* + * The HW is typically unlocked when the SHA hash wc_Sha[nn]Final() is called. + * However, in the case of TS connections, the in progress hash may at times be + * abandoned. Thus this function should be called at free time. See internal.c + */ +int esp_sha_release_unfinished_lock(WC_ESP32SHA* ctx) +{ + int ret = 0; + ret = esp_sha_hw_islocked(ctx); /* get the owner of the current lock */ + if (ret == 0) { + /* no lock */ + } + else { + if (ret == (int)ctx) { + /* found a match for this object */ + if (ret == (int)(ctx->initializer)) { + /* confirmed match*/ + } + else { + /* the only mismatch expected may be in a mullti-thread RTOS */ + ESP_LOGE(TAG, "ERROR: esp_sha_release_unfinished_lock for %x" + " but found %x", ret, (int)(ctx->initializer)); + } + #ifdef DEBUG_WOLFSSL_SHA_MUTEX + ESP_LOGE(TAG, "\n>>>> esp_sha_release_unfinished_lock %x\n", ret); + #endif + /* unlock only if this ctx is the intializer of the lock */ + #ifdef SINGLE_THREADED + { + ret = esp_sha_hw_unlock(ctx); + } + #else + { + if (ctx->task_owner == xTaskGetCurrentTaskHandle()) { + ret = esp_sha_hw_unlock(ctx); + } + else { + /* We cannot free a SHA onbject locks from a different task. + * So give the ctx a hint for the other task to clean it up. */ + ctx->mode = ESP32_SHA_FREED; + } + } + #endif + + } + } + return ret; +} /* ** lock HW engine. ** this should be called before using engine. @@ -668,7 +1105,18 @@ int esp_sha_try_hw_lock(WC_ESP32SHA* ctx) { int ret = 0; - ESP_LOGV(TAG, "enter esp_sha_hw_lock %x", (int)ctx->initializer); +#ifdef WOLFSSL_ESP32_HW_LOCK_DEBUG + ESP_LOGI(TAG, "enter esp_sha_hw_lock for %x", (int)ctx->initializer); +#endif + + #ifdef DEBUG_WOLFSSL_SHA_MUTEX + taskENTER_CRITICAL(&sha_crit_sect); + { + /* let's keep track of how many times we call this */ + _sha_call_count++; + } + taskEXIT_CRITICAL(&sha_crit_sect); + #endif if (ctx == NULL) { ESP_LOGE(TAG, " esp_sha_try_hw_lock called with NULL ctx"); @@ -694,9 +1142,9 @@ int esp_sha_try_hw_lock(WC_ESP32SHA* ctx) else { /* this should not happens */ ESP_LOGE(TAG, "unexpected error in esp_sha_try_hw_lock."); - return -1; + return ESP_FAIL; } -#else /* not defined(SINGLE_THREADED) */ +#else /* not ESP_FAILfined(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. @@ -720,62 +1168,180 @@ int esp_sha_try_hw_lock(WC_ESP32SHA* ctx) /* created, but not yet locked */ ret = esp_CryptHwMutexInit(&sha_mutex); if (ret == 0) { - ESP_LOGV(TAG, "esp_CryptHwMutexInit sha_mutex init success."); + #ifdef DEBUG_WOLFSSL_SHA_MUTEX + ESP_LOGI(TAG, "esp_CryptHwMutexInit sha_mutex init success."); + mutex_ctx_owner = 0; + #endif } else { ESP_LOGE(TAG, "esp_CryptHwMutexInit sha_mutex failed."); sha_mutex = 0; ESP_LOGI(TAG, "Revert to ctx->mode = ESP32_SHA_SW."); + + #ifdef DEBUG_WOLFSSL_SHA_MUTEX + ESP_LOGI(TAG, "Current mutext owner = %x", + (int)esp_sha_mutex_ctx_owner()); + #endif + ctx->mode = ESP32_SHA_SW; - return 0; /* success, just not using HW */ + return ESP_OK; /* success, just not using HW */ + } + } + +#ifdef ESP_MONITOR_HW_TASK_LOCK + if (mutex_ctx_task == 0 || mutex_ctx_owner == 0) { + /* no known stray mutex task owner */ + } + else { + if (mutex_ctx_task == xTaskGetCurrentTaskHandle()) { + ESP_LOGI(TAG, "Found mutex_ctx_task"); + if (((WC_ESP32SHA*)mutex_ctx_owner)->mode == ESP32_SHA_FREED) { + ESP_LOGW(TAG, "ESP32_SHA_FREED unlocking mutex_ctx_task = %x" + " for mutex_ctx_owner = %x", + (int)mutex_ctx_task, (int)mutex_ctx_owner ); + esp_CryptHwMutexUnLock(&sha_mutex); + ((WC_ESP32SHA*)mutex_ctx_owner)->mode = ESP32_SHA_INIT; + mutex_ctx_task = 0; + mutex_ctx_owner = 0; + } + else { + if (ctx->mode == ESP32_SHA_FREED) { + ESP_LOGW(TAG, "ESP32_SHA_FREED unlocking ctx = %x" + " for ctx.initializer = %x", + (int)ctx, (int)ctx->initializer ); + esp_CryptHwMutexUnLock(&sha_mutex); + ctx->mode = ESP32_SHA_INIT; + mutex_ctx_task = 0; + mutex_ctx_owner = 0; + } + } } } +#endif /* ESP_MONITOR_HW_TASK_LOCK */ /* 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 */ - ESP_LOGV(TAG, "ESP32_SHA_INIT\n"); +#ifdef WOLFSSL_ESP32_HW_LOCK_DEBUG + ESP_LOGI(TAG, "ESP32_SHA_INIT for %x\n", (int)ctx->initializer); +#endif + /* lock hardware; there should be exactly one instance + * of esp_CryptHwMutexLock(&sha_mutex ...) in code. + * + * we don't wait: + * either the engine is free, or we fall back to SW. + * + * TODO: allow for SHA interleave on chips that support it. + */ - /* we don't wait: - ** either the engine is free, or we fall back to SW - **/ if (esp_CryptHwMutexLock(&sha_mutex, (TickType_t)0) == 0) { + /* we've successfully locked */ + #ifdef ESP_MONITOR_HW_TASK_LOCK + mutex_ctx_task = xTaskGetCurrentTaskHandle(); + #endif + + #ifdef DEBUG_WOLFSSL_SHA_MUTEX + if (esp_sha_call_count() == 8 && WOLFSSL_TEST_STRAY) { + /* once we've locked 10 times here, + * we'll force a fallback to SW until other thread unlocks */ + taskENTER_CRITICAL(&sha_crit_sect); + { + (void)stray_ctx; + if (stray_ctx == NULL) { + /* no peek task */ + } + else { + stray_ctx->initializer = stray_ctx; + mutex_ctx_owner = (void*)stray_ctx->initializer; + } + } + taskEXIT_CRITICAL(&sha_crit_sect); + if (stray_ctx == NULL) { + ESP_LOGW(TAG, "DEBUG_WOLFSSL_SHA_MUTEX on, but stray_ctx " + "is NULL; are you running the peek task to " + "set the stay test?"); + } + else { + ESP_LOGI(TAG, "%x", (int)stray_ctx->initializer); + ESP_LOGI(TAG, "%x", (int)&stray_ctx); + ESP_LOGW(TAG, + "\n\nLocking with stray\n\n" + "DEBUG_WOLFSSL_SHA_MUTEX call count 8, " + "ctx->mode = ESP32_SHA_SW %x\n\n", + (int)mutex_ctx_owner); + ctx->task_owner = xTaskGetCurrentTaskHandle(); + ctx->mode = ESP32_SHA_SW; + return ESP_OK; /* success, but revert to SW */ + } + } + #endif + /* check to see if we had a prior fail and need to unroll enables */ + #ifdef WOLFSSL_ESP32_HW_LOCK_DEBUG + ESP_LOGW(TAG, "Locking for ctx %x, current mutex_ctx_owner = %x", + (int)&ctx, (int)esp_sha_mutex_ctx_owner()); + #endif ret = esp_unroll_sha_module_enable(ctx); - ESP_LOGV(TAG, "Hardware Mode, lock depth = %d, %x", + #ifdef WOLFSSL_ESP32_HW_LOCK_DEBUG + ESP_LOGI(TAG, "Hardware Mode Active, lock depth = %d, for %x", ctx->lockDepth, (int)ctx->initializer); + #endif + #ifdef DEBUG_WOLFSSL_SHA_MUTEX + taskENTER_CRITICAL(&sha_crit_sect); + { + mutex_ctx_owner = (void*)ctx->initializer; + /* let's keep track of how many times we lock this */ + _sha_lock_count++; + } + taskEXIT_CRITICAL(&sha_crit_sect); + #endif 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", + "interesting lock depth = %d, for this %x", ctx->lockDepth, (int)ctx->initializer); } } else { /* We should have otherwise anticipated this; how did we get here? ** This code should rarely, ideally never be reached. */ - #if defined(DEBUG_WOLFSSL) - ESP_LOGI(TAG, "\nHardware in use; Mode REVERT to ESP32_SHA_SW\n"); + #ifdef DEBUG_WOLFSSL_SHA_MUTEX + ESP_LOGI(TAG, "\nHardware in use by %x; " + "Mode REVERT to ESP32_SHA_SW for %x\n", + (int)esp_sha_mutex_ctx_owner(), + (int)ctx->initializer); + ESP_LOGI(TAG, "Software Mode, lock depth = %d, for this %x", + ctx->lockDepth, (int)ctx->initializer); + ESP_LOGI(TAG, "Current mutext owner = %x", + (int)esp_sha_mutex_ctx_owner()); #endif ctx->mode = ESP32_SHA_SW; - return 0; /* success, but revert to SW */ + return ESP_OK; /* 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."); - return -1; + return ESP_FAIL; } #endif /* not defined(SINGLE_THREADED) */ #if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) - /* ESP32-C3 RISC-V TODO */ + ESP_LOGV(TAG, "ets_sha_enable for RISC-V"); + ets_sha_enable(); + ctx->mode = ESP32_SHA_HW; #else if (ret == 0) { ctx->lockDepth++; /* depth for THIS ctx (there could be others!) */ + #ifdef WOLFSSL_ESP32_HW_LOCK_DEBUG + { + printf("1) Lock depth @ %d = %d for WC_ESP32SHA @ %0x\n", + __LINE__, ctx->lockDepth, (unsigned)ctx); + } + #endif periph_module_enable(PERIPH_SHA_MODULE); ctx->mode = ESP32_SHA_HW; } @@ -790,14 +1356,21 @@ int esp_sha_try_hw_lock(WC_ESP32SHA* ctx) } /* 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. +** Note this is not the semaphore tracking who has the HW. */ int esp_sha_hw_unlock(WC_ESP32SHA* ctx) { + int ret; +#ifdef WOLFSSL_ESP32_HW_LOCK_DEBUG ESP_LOGV(TAG, "enter esp_sha_hw_unlock"); +#endif + ret = 0; #if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) - /* ESP32-C3 RISC-V TODO */ + /* ESP32-C3 and ESP32-C6 RISC-V */ + ets_sha_disable(); /* disable also resets active, ongoing hash */ + ESP_LOGV(TAG, "ets_sha_disable in esp_sha_hw_unlock()"); #else /* Disable AES hardware */ periph_module_disable(PERIPH_SHA_MODULE); @@ -807,6 +1380,10 @@ int esp_sha_hw_unlock(WC_ESP32SHA* ctx) * and periph_module_disable() need to be unwound. * * see ref_counts[periph] in file: periph_ctrl.c */ +#ifdef WOLFSSL_ESP32_HW_LOCK_DEBUG + printf("2) esp_sha_hw_unlock Lock depth @ %d = %d for WC_ESP32SHA @ %0x\n", + __LINE__, ctx->lockDepth, (unsigned)ctx); +#endif if (ctx->lockDepth > 0) { ctx->lockDepth--; } @@ -814,14 +1391,50 @@ int esp_sha_hw_unlock(WC_ESP32SHA* ctx) ctx->lockDepth = 0; } -#if defined(SINGLE_THREADED) - InUse = 0; -#else - /* unlock HW engine for next use */ - esp_CryptHwMutexUnLock(&sha_mutex); +#if defined(ESP_MONITOR_HW_TASK_LOCK) && defined(WOLFSSL_ESP32_HW_LOCK_DEBUG) + printf("3) esp_sha_hw_unlock Lock depth @ %d = %d for WC_ESP32SHA @ %0x\n", + __LINE__, ctx->lockDepth, (unsigned)ctx); #endif - ESP_LOGV(TAG, "leave esp_sha_hw_unlock, %x", (int)ctx->initializer); - return 0; + if (0 == ctx->lockDepth) + { + #if defined(SINGLE_THREADED) + InUse = 0; + #else + /* unlock HW engine for next use */ + #ifdef WOLFSSL_ESP32_HW_LOCK_DEBUG + { + ESP_LOGW(TAG, "Unlocking for %x, from ctx %x, & = %x, " + "mutex_ctx_owner = %x", + (int)esp_sha_mutex_ctx_owner(), + (int)ctx, + (int)&ctx, + (int)esp_sha_mutex_ctx_owner()); + ESP_LOGW(TAG, "&sha_mutex = %x", (int)&sha_mutex); + } + #endif /* WOLFSSL_ESP32_HW_LOCK_DEBUG */ + esp_CryptHwMutexUnLock(&sha_mutex); + #ifdef ESP_MONITOR_HW_TASK_LOCK + mutex_ctx_task = 0; + #endif + #endif + + #ifdef DEBUG_WOLFSSL_SHA_MUTEX + taskENTER_CRITICAL(&sha_crit_sect); + { + mutex_ctx_owner = 0; + } + taskEXIT_CRITICAL(&sha_crit_sect); + #endif + } + else + { + ESP_LOGE(TAG, "ERROR unlock lockDepth not zero"); + ret = ESP_FAIL; + } +#ifdef WOLFSSL_ESP32_HW_LOCK_DEBUG + ESP_LOGI(TAG, "leave esp_sha_hw_unlock, %x", (int)ctx->initializer); +#endif + return ret; } /* esp_sha_hw_unlock */ /* @@ -829,10 +1442,12 @@ int esp_sha_hw_unlock(WC_ESP32SHA* ctx) * Assumes register already loaded. * Returns a negative value error code upon failure. */ +#if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C6) +/* the ESP32-C3 HAL has built-in process start, everything else uses: */ static int esp_sha_start_process(WC_ESP32SHA* sha) { int ret = 0; -#if defined(CONFIG_IDF_TARGET_ESP32S3) +#if defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3) uint8_t HardwareAlgorithm; #endif @@ -842,16 +1457,38 @@ static int esp_sha_start_process(WC_ESP32SHA* sha) ESP_LOGV(TAG, " enter esp_sha_start_process"); - #if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) - /* ESP32-C3 RISC-V TODO */ - #elif defined(CONFIG_IDF_TARGET_ESP32S3) +#if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) + ESP_LOGV(TAG, "SHA1 SHA_START_REG"); + if (sha->isfirstblock) { + sha_ll_start_block(SHA2_256); + 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 { + sha_ll_continue_block(SHA2_256); + #if defined(DEBUG_WOLFSSL) + this_block_num++; /* one-based counter */ + ESP_LOGV(TAG, " continue block #%d", this_block_num); + #endif + } /* not first block */ + /***** END CONFIG_IDF_TARGET_ESP32C3 or CONFIG_IDF_TARGET_ESP32C6 *****/ + +#elif defined(CONFIG_IDF_TARGET_ESP32S2) || 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_224: + HardwareAlgorithm = 1; + break; case SHA2_256: HardwareAlgorithm = 2; break; @@ -868,7 +1505,7 @@ static int esp_sha_start_process(WC_ESP32SHA* sha) default: /* Unsupported SHA mode. */ sha->mode = ESP32_SHA_FAIL_NEED_UNROLL; - return -1; + return ESP_FAIL; } REG_WRITE(SHA_MODE_REG, HardwareAlgorithm); @@ -892,7 +1529,9 @@ static int esp_sha_start_process(WC_ESP32SHA* sha) #endif } /* not first block */ -#else /* not ESP32S3 */ + /* end ESP32S3 */ + +#elif defined(CONFIG_IDF_TARGET_ESP32) if (sha->isfirstblock) { /* start registers for first message block * we don't make any relational memory position assumptions. @@ -920,7 +1559,7 @@ static int esp_sha_start_process(WC_ESP32SHA* sha) default: sha->mode = ESP32_SHA_FAIL_NEED_UNROLL; - ret = -1; + ret = ESP_FAIL; break; } @@ -962,10 +1601,13 @@ static int esp_sha_start_process(WC_ESP32SHA* sha) default: /* error for unsupported other values */ sha->mode = ESP32_SHA_FAIL_NEED_UNROLL; - ret = -1; + ret = ESP_FAIL; break; } } + /* end standard ESP32 */ + #else + ESP_LOGE(TAG, "Unsupported hardware"); #endif #if defined(DEBUG_WOLFSSL) @@ -977,6 +1619,7 @@ static int esp_sha_start_process(WC_ESP32SHA* sha) return ret; } +#endif /* esp_sha_start_process !CONFIG_IDF_TARGET_ESP32C3/C6 */ /* ** process message block @@ -985,13 +1628,15 @@ static int wc_esp_process_block(WC_ESP32SHA* ctx, /* see ctx->sha_type */ const word32* data, word32 len) { - int ret = 0; /* assume success */ + int ret = ESP_OK; /* assume success */ word32 word32_to_save = (len) / (sizeof(word32)); -#ifdef CONFIG_IDF_TARGET_ESP32S3 - uint32_t* MessageSource; - uint32_t* AcceleratorMessage; -#else +#if defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3) + word32* MessageSource; + word32* AcceleratorMessage; +#elif CONFIG_IDF_TARGET_ESP32 int i; +#else + /* not used */ #endif ESP_LOGV(TAG, " enter esp_process_block"); if (word32_to_save > 0x31) { @@ -1002,43 +1647,116 @@ static int wc_esp_process_block(WC_ESP32SHA* ctx, /* see ctx->sha_type */ /* 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--) */ - -#else +#if defined(CONFIG_IDF_TARGET_ESP32) /* 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 endianness. * * a useful watch array cast to watch at runtime: - * ((uint32_t[32]) (*(volatile uint32_t *)(SHA_TEXT_BASE))) + * ((word32[32]) (*(volatile word32 *)(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 * see ctx->sha_type * reg data does not change until we are ready to read */ ret = esp_sha_start_process(ctx); + /***** END CONFIG_IDF_TARGET_ESP32 */ + +#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) + /* SHA_M_1_REG is not a macro: + * DPORT_REG_WRITE(SHA_M_1_REG + (i*sizeof(word32)), *(data + i)); + * + * but we have this HAL: sha_ll_fill_text_block + * + * Note that unlike the plain ESP32 that has only 1 register, we can write + * the entire block. + * SHA_TEXT_BASE = 0x6003b080 + * SHA_H_BASE = 0x6003b040 + * see hash: (word32[08]) (*(volatile uint32_t *)(SHA_H_BASE)) + * message: (word32[16]) (*(volatile uint32_t *)(SHA_TEXT_BASE)) + * ((word32[16]) (*(volatile uint32_t *)(SHA_TEXT_BASE))) + */ + if (&data != _active_digest_address) { + ESP_LOGV(TAG, "TODO Moving alternate ctx->for_digest"); + /* move last known digest into HW reg during interleave */ + /* sha_ll_write_digest(ctx->sha_type, ctx->for_digest, + WC_SHA256_BLOCK_SIZE); */ + _active_digest_address = &data; + } + if (ctx->isfirstblock) { + ets_sha_enable(); /* will clear initial digest */ + #if defined(DEBUG_WOLFSSL) + { + this_block_num = 1; /* one-based counter, just for debug info */ + } + #endif + } + else { + #if defined(DEBUG_WOLFSSL) + { + this_block_num++; + } + #endif + } + /* call Espressif HAL for this hash*/ + sha_hal_hash_block(ctx->sha_type, + (void *)(data), + word32_to_save, + ctx->isfirstblock); + ctx->isfirstblock = 0; /* once we hash a block, + * we're no longer at the first */ + /***** END CONFIG_IDF_TARGET_ESP32C3 or CONFIG_IDF_TARGET_ESP32C6 */ + +#elif defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3) + MessageSource = (word32*)data; + AcceleratorMessage = (word32*)(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--) */ + /* notify HW to start process + * see ctx->sha_type + * reg data does not change until we are ready to read */ + ret = esp_sha_start_process(ctx); + /***** END CONFIG_IDF_TARGET_ESP32S2 or CONFIG_IDF_TARGET_ESP32S3 */ + +#else + ret = ESP_FAIL; + ESP_LOGE(TAG, "ERROR: (CONFIG_IDF_TARGET not supported"); +#endif + +#ifdef WOLFSSL_HW_METRICS + switch (ctx->sha_type) { + case SHA1: + esp_sha1_hw_hash_usage_ct++; + break; + + #ifndef NO_WOLFSSL_ESP32_CRYPT_HASH_SHA224 + case SHA2_224: + esp_sha2_224_hw_hash_usage_ct++; + break; + #endif + + case SHA2_256: + esp_sha2_256_hw_hash_usage_ct++; + break; + + default: + break; + } +#endif ESP_LOGV(TAG, " leave esp_process_block"); return ret; @@ -1051,12 +1769,12 @@ int wc_esp_digest_state(WC_ESP32SHA* ctx, byte* hash) { word32 digestSz; -#if CONFIG_IDF_TARGET_ESP32S3 +#if defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3) uint64_t* pHash64Buffer; uint32_t* pHashDestination; size_t szHashWords; size_t szHash64Words; -# endif +#endif ESP_LOGV(TAG, "enter esp_digest_state"); @@ -1065,16 +1783,32 @@ int wc_esp_digest_state(WC_ESP32SHA* ctx, byte* hash) } /* sanity check */ +#if defined(CONFIG_IDF_TARGET_ESP32) + if (ctx->sha_type == SHA_INVALID) { +#elif defined(CONFIG_IDF_TARGET_ESP32C3) || \ + defined(CONFIG_IDF_TARGET_ESP32S2) || \ + defined(CONFIG_IDF_TARGET_ESP32S3) || \ + defined(CONFIG_IDF_TARGET_ESP32C6) + if (ctx->sha_type == SHA_TYPE_MAX) { +#else + ESP_LOGE(TAG, "unexpected target for wc_esp_digest_state"); + { +#endif /* conditional sanity check on she_type */ + ctx->mode = ESP32_SHA_FAIL_NEED_UNROLL; + ESP_LOGE(TAG, "error. sha_type %d is invalid.", ctx->sha_type); + return ESP_FAIL; + } + 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; + return ESP_FAIL; } -#if CONFIG_IDF_TARGET_ESP32S3 +#if defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3) if (ctx->isfirstblock == true) { /* no hardware use yet. Nothing to do yet */ - return 0; + return ESP_OK; } /* wait until idle */ @@ -1082,7 +1816,7 @@ int wc_esp_digest_state(WC_ESP32SHA* ctx, byte* hash) /* read hash result into buffer & flip endianness */ pHashDestination = (uint32_t*)hash; - szHashWords = wc_esp_sha_digest_size(ctx->sha_type) / sizeof(uint32_t); + szHashWords = wc_esp_sha_digest_size(ctx->sha_type) / sizeof(word32); esp_dport_access_read_buffer(pHashDestination, SHA_H_BASE, szHashWords); if (ctx->sha_type == SHA2_512) { @@ -1103,6 +1837,10 @@ int wc_esp_digest_state(WC_ESP32SHA* ctx, byte* hash) } /* not (ctx->sha_type == SHA2_512) */ /* end if CONFIG_IDF_TARGET_ESP32S3 */ +#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) + sha_ll_read_digest(ctx->sha_type, + (void *)hash, + wc_esp_sha_digest_size(ctx->sha_type) / sizeof(word32)); #else /* not CONFIG_IDF_TARGET_ESP32S3 */ /* wait until idle */ @@ -1110,7 +1848,9 @@ int wc_esp_digest_state(WC_ESP32SHA* ctx, byte* hash) /* 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 */ + +#elif defined(CONFIG_IDF_TARGET_ESP32S2) + #else switch (ctx->sha_type) { case SHA1: @@ -1135,12 +1875,12 @@ int wc_esp_digest_state(WC_ESP32SHA* ctx, byte* hash) default: ctx->mode = ESP32_SHA_FAIL_NEED_UNROLL; - return -1; + return ESP_FAIL; } if (ctx->isfirstblock == true) { /* no hardware use yet. Nothing to do yet */ - return 0; + return ESP_OK; } /* LOAD final digest */ @@ -1164,11 +1904,11 @@ int wc_esp_digest_state(WC_ESP32SHA* ctx, byte* hash) */ esp_dport_access_read_buffer( -#if ESP_IDF_VERSION_MAJOR >= 4 + #if ESP_IDF_VERSION_MAJOR >= 4 (uint32_t*)(hash), /* the result will be found in hash upon exit */ -#else + #else (word32*)(hash), /* the result will be found in hash upon exit */ -#endif + #endif SHA_TEXT_BASE, /* there's a fixed reg addr for all SHA */ digestSz / sizeof(word32) /* # 4-byte */ ); @@ -1186,10 +1926,10 @@ int wc_esp_digest_state(WC_ESP32SHA* ctx, byte* hash) } } #endif -#endif /* not CONFIG_IDF_TARGET_ESP32S3 */ +#endif /* not CONFIG_IDF_TARGET_ESP32S3, C3, else... */ ESP_LOGV(TAG, "leave esp_digest_state"); - return 0; + return ESP_OK; } /* wc_esp_digest_state */ #ifndef NO_SHA @@ -1231,7 +1971,7 @@ int esp_sha_digest_process(struct wc_Sha* sha, byte blockprocess) #endif /* NO_SHA */ -#ifndef NO_SHA256 +#if !defined(NO_SHA256) && !defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA256) /* ** sha256 process ** @@ -1243,17 +1983,33 @@ int esp_sha256_process(struct wc_Sha256* sha, const byte* data) ESP_LOGV(TAG, " enter esp_sha256_process"); - if ((&sha->ctx)->sha_type == SHA2_256) { + switch ((&sha->ctx)->sha_type) { + case SHA2_256: #if defined(DEBUG_WOLFSSL_VERBOSE) - ESP_LOGV(TAG, " confirmed SHA type call match"); + ESP_LOGV(TAG, " confirmed SHA256 type call match"); #endif - } - else { - ret = -1; + wc_esp_process_block(&sha->ctx, + (const word32*)data, + WC_SHA256_BLOCK_SIZE); + break; + +#ifndef NO_WOLFSSL_ESP32_CRYPT_HASH_SHA224 + case SHA2_224: + #if defined(DEBUG_WOLFSSL_VERBOSE) + ESP_LOGV(TAG, " confirmed SHA224 type call match"); + #endif + wc_esp_process_block(&sha->ctx, + (const word32*)data, + WC_SHA224_BLOCK_SIZE); + break; +#endif + + default: + ret = ESP_FAIL; ESP_LOGE(TAG, " ERROR SHA type call mismatch"); + break; } - wc_esp_process_block(&sha->ctx, (const word32*)data, WC_SHA256_BLOCK_SIZE); ESP_LOGV(TAG, " leave esp_sha256_process"); @@ -1268,16 +2024,17 @@ int esp_sha256_process(struct wc_Sha256* sha, const byte* data) */ int esp_sha256_digest_process(struct wc_Sha256* sha, byte blockprocess) { - int ret = 0; + int ret = ESP_OK; ESP_LOGV(TAG, "enter esp_sha256_digest_process"); +#ifndef NO_WOLFSSL_ESP32_CRYPT_HASH_SHA256 if (blockprocess) { wc_esp_process_block(&sha->ctx, sha->buffer, WC_SHA256_BLOCK_SIZE); } wc_esp_digest_state(&sha->ctx, (byte*)sha->digest); - +#endif ESP_LOGV(TAG, "leave esp_sha256_digest_process"); return ret; } /* esp_sha256_digest_process */ @@ -1294,7 +2051,7 @@ 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 !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C6) /* note that in SW mode, wolfSSL uses 64 bit words */ if (sha->ctx.mode == ESP32_SHA_SW) { ByteReverseWords64(sha->buffer, @@ -1323,6 +2080,7 @@ int esp_sha512_block(struct wc_Sha512* sha, const word32* data, byte isfinal) ret = wc_esp_process_block(&sha->ctx, data, WC_SHA512_BLOCK_SIZE); } ESP_LOGV(TAG, "leave esp_sha512_block"); +#endif return ret; } /* esp_sha512_block */ @@ -1349,7 +2107,9 @@ int esp_sha512_digest_process(struct wc_Sha512* sha, byte blockproc) { int ret = 0; ESP_LOGV(TAG, "enter esp_sha512_digest_process"); - +#if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) + ESP_LOGW(TAG, "Warning: no SHA512 HW to digest on ESP32-C3"); +#else if (blockproc) { word32* data = (word32*)sha->buffer; @@ -1363,8 +2123,54 @@ int esp_sha512_digest_process(struct wc_Sha512* sha, byte blockproc) } ESP_LOGV(TAG, "leave esp_sha512_digest_process"); +#endif return ret; } /* esp_sha512_digest_process */ #endif /* WOLFSSL_SHA512 || WOLFSSL_SHA384 */ #endif /* WOLFSSL_ESP32_CRYPT */ #endif /* !defined(NO_SHA) ||... */ + +#if defined(WOLFSSL_ESP32_CRYPT) && defined(WOLFSSL_HW_METRICS) +int esp_sw_sha256_count_add(void) { + esp_sha256_sw_fallback_usage_ct++; + return esp_sha256_sw_fallback_usage_ct; +} + +int esp_hw_show_sha_metrics(void) +{ + int ret = 0; +#ifdef WOLFSSL_ESP32_CRYPT + ESP_LOGI(TAG, "--------------------------------------------------------"); + ESP_LOGI(TAG, "------------- wolfSSL ESP HW SHA Metrics----------------"); + ESP_LOGI(TAG, "--------------------------------------------------------"); + + ESP_LOGI(TAG, "esp_sha_hw_copy_ct = %lu", + esp_sha_hw_copy_ct); + ESP_LOGI(TAG, "esp_sha1_hw_usage_ct = %lu", + esp_sha1_hw_usage_ct); + ESP_LOGI(TAG, "esp_sha1_sw_fallback_usage_ct = %lu", + esp_sha1_sw_fallback_usage_ct); + ESP_LOGI(TAG, "esp_sha_reverse_words_ct = %lu", + esp_sha_reverse_words_ct); + ESP_LOGI(TAG, "esp_sha1_hw_hash_usage_ct = %lu", + esp_sha1_hw_hash_usage_ct); + ESP_LOGI(TAG, "esp_sha2_224_hw_hash_usage_ct = %lu", + esp_sha2_224_hw_hash_usage_ct); + ESP_LOGI(TAG, "esp_sha2_256_hw_hash_usage_ct = %lu", + esp_sha2_256_hw_hash_usage_ct); + ESP_LOGI(TAG, "esp_byte_reversal_checks_ct = %lu", + esp_byte_reversal_checks_ct); + ESP_LOGI(TAG, "esp_byte_reversal_needed_ct = %lu", + esp_byte_reversal_needed_ct); + +#else + /* no HW math, no HW math metrics */ + ret = 0; +#endif /* HW_MATH_ENABLED */ + + + return ret; +} +#endif /* WOLFSSL_HW_METRICS */ + +#endif /* WOLFSSL_ESPIDF */ diff --git a/wolfcrypt/src/port/Espressif/esp32_util.c b/wolfcrypt/src/port/Espressif/esp32_util.c index 809c62bec1..c247125ab5 100644 --- a/wolfcrypt/src/port/Espressif/esp32_util.c +++ b/wolfcrypt/src/port/Espressif/esp32_util.c @@ -19,6 +19,28 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ +#ifdef HAVE_CONFIG_H + #include +#endif + +/* Reminder: user_settings.h is needed and included from settings.h + * Be sure to define WOLFSSL_USER_SETTINGS, typically in CMakeLists.txt */ +#include + +#if defined(WOLFSSL_ESPIDF) /* Entire file is only for Espressif EDP-IDF */ +#include "sdkconfig.h" /* programmatically generated from sdkconfig */ +#include + +/* Espressif */ +#include +#include +#include + +/* wolfSSL */ +#include /* needed to print MATH_INT_T value */ +#include +#include + /* ** Version / Platform info. ** @@ -26,23 +48,25 @@ ** https://github.com/wolfSSL/wolfssl/pull/6149 */ -#include -#include - -#include /* needed to print MATH_INT_T value */ - -#if defined(WOLFSSL_ESPIDF) - #include - #include "sdkconfig.h" - #define WOLFSSL_VERSION_PRINTF(...) ESP_LOGI(TAG, __VA_ARGS__) -#else - #include - #define WOLFSSL_VERSION_PRINTF(...) { printf(__VA_ARGS__); printf("\n"); } -#endif +#define WOLFSSL_VERSION_PRINTF(...) ESP_LOGI(TAG, __VA_ARGS__) +/* + * If used in other platforms: + * #include + * #define WOLFSSL_VERSION_PRINTF(...) { printf(__VA_ARGS__); printf("\n"); } + */ static const char* TAG = "esp32_util"; -/* some functions are only applicable when hardware encryption is enabled */ +/* Variable holding number of times ESP32 restarted since first boot. + * It is placed into RTC memory using RTC_DATA_ATTR and + * maintains its value when ESP32 wakes from deep sleep. + */ +RTC_DATA_ATTR static int _boot_count = 0; +static int esp_ShowMacroStatus_need_header = 0; +/* Some helpers for macro display */ +#define STRING_OF(macro) #macro +#define STR_IFNDEF(macro) STRING_OF(macro) + #if defined(WOLFSSL_ESP32_CRYPT) && \ (!defined(NO_AES) || !defined(NO_SHA) || !defined(NO_SHA256) ||\ defined(WOLFSSL_SHA384) || defined(WOLFSSL_SHA512)) @@ -51,6 +75,7 @@ static const char* TAG = "esp32_util"; #include #include +/* big nums can be very long, perhaps unitialized, so limit displayed words */ #define MAX_WORDS_ESP_SHOW_MP 32 /* @@ -62,7 +87,7 @@ static const char* TAG = "esp32_util"; * other value from wc_InitMutex() * */ -WOLFSSL_LOCAL int esp_CryptHwMutexInit(wolfSSL_Mutex* mutex) { +int esp_CryptHwMutexInit(wolfSSL_Mutex* mutex) { if (mutex == NULL) { return BAD_MUTEX_E; } @@ -72,9 +97,10 @@ WOLFSSL_LOCAL int esp_CryptHwMutexInit(wolfSSL_Mutex* mutex) { /* * call the ESP-IDF mutex lock; xSemaphoreTake - * + * this is a general mutex locker, used for different mutex objects for + * different HW acclerators or other single-use HW features. */ -WOLFSSL_LOCAL int esp_CryptHwMutexLock(wolfSSL_Mutex* mutex, TickType_t block_time) { +int esp_CryptHwMutexLock(wolfSSL_Mutex* mutex, TickType_t block_time) { if (mutex == NULL) { WOLFSSL_ERROR_MSG("esp_CryptHwMutexLock called with null mutex"); return BAD_MUTEX_E; @@ -83,7 +109,7 @@ WOLFSSL_LOCAL int esp_CryptHwMutexLock(wolfSSL_Mutex* mutex, TickType_t block_ti #ifdef SINGLE_THREADED return wc_LockMutex(mutex); /* xSemaphoreTake take with portMAX_DELAY */ #else - return ((xSemaphoreTake( *mutex, block_time ) == pdTRUE) ? 0 : BAD_MUTEX_E); + return ((xSemaphoreTake(*mutex, block_time) == pdTRUE) ? 0 : BAD_MUTEX_E); #endif } @@ -91,7 +117,7 @@ WOLFSSL_LOCAL int esp_CryptHwMutexLock(wolfSSL_Mutex* mutex, TickType_t block_ti * call the ESP-IDF mutex UNlock; xSemaphoreGive * */ -WOLFSSL_LOCAL int esp_CryptHwMutexUnLock(wolfSSL_Mutex* mutex) { +int esp_CryptHwMutexUnLock(wolfSSL_Mutex* mutex) { if (mutex == NULL) { WOLFSSL_ERROR_MSG("esp_CryptHwMutexLock called with null mutex"); return BAD_MUTEX_E; @@ -101,7 +127,7 @@ WOLFSSL_LOCAL int esp_CryptHwMutexUnLock(wolfSSL_Mutex* mutex) { return wc_UnLockMutex(mutex); #else xSemaphoreGive(*mutex); - return 0; + return ESP_OK; #endif } #endif /* WOLFSSL_ESP32_CRYPT, etc. */ @@ -122,7 +148,7 @@ WOLFSSL_LOCAL int esp_CryptHwMutexUnLock(wolfSSL_Mutex* mutex) { ** Specific platforms: Espressif */ #if defined(WOLFSSL_ESPIDF) -static int ShowExtendedSystemInfo_platform_espressif() +static int ShowExtendedSystemInfo_platform_espressif(void) { #if defined(CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ) WOLFSSL_VERSION_PRINTF("CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ: %u MHz", @@ -161,8 +187,13 @@ static int ShowExtendedSystemInfo_platform_espressif() char thisHWM = 0; WOLFSSL_VERSION_PRINTF("Stack HWM: %x", (size_t) &thisHWM); #else - WOLFSSL_VERSION_PRINTF("Stack HWM: %d", - uxTaskGetStackHighWaterMark(NULL)); + #ifdef INCLUDE_uxTaskGetStackHighWaterMark + { + WOLFSSL_VERSION_PRINTF("Stack HWM: %d", + uxTaskGetStackHighWaterMark(NULL)); + } + #endif /* INCLUDE_uxTaskGetStackHighWaterMark */ + #endif #elif CONFIG_IDF_TARGET_ESP32S2 @@ -190,42 +221,62 @@ static int ShowExtendedSystemInfo_platform_espressif() #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("ESP32_CRYPT is enabled for ESP32."); -#elif defined(CONFIG_IDF_TARGET_ESP32S2) - WOLFSSL_VERSION_PRINTF("ESP32_CRYPT is enabled for ESP32-S2."); -#elif defined(CONFIG_IDF_TARGET_ESP32S3) - WOLFSSL_VERSION_PRINTF("ESP32_CRYPT is enabled for ESP32-S3."); -#elif defined(CONFIG_IDF_TARGET_ESP32C3) - WOLFSSL_VERSION_PRINTF("ESP32_CRYPT is enabled for ESP32-C3."); -#elif defined(CONFIG_IDF_TARGET_ESP32C6) - WOLFSSL_VERSION_PRINTF("ESP32_CRYPT is enabled for ESP32-C6."); -#elif defined(CONFIG_IDF_TARGET_ESP32H2) - WOLFSSL_VERSION_PRINTF("ESP32_CRYPT is enabled for ESP32-H2."); -#else - /* this should have been detected & disabled in user_settins.h */ - #error "ESP32_CRYPT not yet supported on this IDF TARGET" -#endif + #if defined(CONFIG_IDF_TARGET_ESP32) + WOLFSSL_VERSION_PRINTF("ESP32_CRYPT is enabled for ESP32."); + #elif defined(CONFIG_IDF_TARGET_ESP32S2) + WOLFSSL_VERSION_PRINTF("ESP32_CRYPT is enabled for ESP32-S2."); + #elif defined(CONFIG_IDF_TARGET_ESP32S3) + WOLFSSL_VERSION_PRINTF("ESP32_CRYPT is enabled for ESP32-S3."); + #elif defined(CONFIG_IDF_TARGET_ESP32C3) + WOLFSSL_VERSION_PRINTF("ESP32_CRYPT is enabled for ESP32-C3."); + #elif defined(CONFIG_IDF_TARGET_ESP32C6) + WOLFSSL_VERSION_PRINTF("ESP32_CRYPT is enabled for ESP32-C6."); + #elif defined(CONFIG_IDF_TARGET_ESP32H2) + WOLFSSL_VERSION_PRINTF("ESP32_CRYPT is enabled for ESP32-H2."); + #else + /* this should have been detected & disabled in user_settins.h */ + #error "ESP32_CRYPT not yet supported on this IDF TARGET" + #endif - /* Even though enabled, some specifics may be disabled */ -#if defined(NO_WOLFSSL_ESP32_CRYPT_HASH) - WOLFSSL_VERSION_PRINTF("NO_WOLFSSL_ESP32_CRYPT_HASH is defined!" - "(disabled HW SHA)."); -#endif + /* Even though enabled, some specifics may be disabled */ + #if defined(NO_WOLFSSL_ESP32_CRYPT_HASH) + WOLFSSL_VERSION_PRINTF("NO_WOLFSSL_ESP32_CRYPT_HASH is defined!" + "(disabled HW SHA)."); + #endif -#if defined(NO_WOLFSSL_ESP32_CRYPT_AES) - WOLFSSL_VERSION_PRINTF("NO_WOLFSSL_ESP32_CRYPT_AES is defined!" - "(disabled HW AES)."); -#endif + #if defined(NO_WOLFSSL_ESP32_CRYPT_AES) + WOLFSSL_VERSION_PRINTF("NO_WOLFSSL_ESP32_CRYPT_AES is defined!" + "(disabled HW AES)."); + #endif -#if defined(NO_WOLFSSL_ESP32_CRYPT_RSA_PRI) - WOLFSSL_VERSION_PRINTF("NO_WOLFSSL_ESP32_CRYPT_RSA_PRI defined!" - "(disabled HW RSA)"); + #if defined(NO_WOLFSSL_ESP32_CRYPT_RSA_PRI) + WOLFSSL_VERSION_PRINTF("NO_WOLFSSL_ESP32_CRYPT_RSA_PRI defined!" + "(disabled HW RSA)"); + #endif #endif -#endif /* ! NO_ESP32_CRYPT */ +#if defined(WOLFSSL_SM2) || defined(WOLFSSL_SM3) || defined(WOLFSSL_SM4) + WOLFSSL_VERSION_PRINTF("SM Ciphers enabled"); + #if defined(WOLFSSL_SM2) + WOLFSSL_VERSION_PRINTF(" WOLFSSL_SM2 enabled"); + #else + WOLFSSL_VERSION_PRINTF(" WOLFSSL_SM2 NOT enabled"); + #endif - return 0; + #if defined(WOLFSSL_SM3) + WOLFSSL_VERSION_PRINTF(" WOLFSSL_SM3 enabled"); + #else + WOLFSSL_VERSION_PRINTF(" WOLFSSL_SM3 NOT enabled"); + #endif + + #if defined(WOLFSSL_SM4) + WOLFSSL_VERSION_PRINTF(" WOLFSSL_SM4 enabled"); + #else + WOLFSSL_VERSION_PRINTF(" WOLFSSL_SM4 NOT enabled"); + #endif +#endif + + return ESP_OK; } #endif @@ -238,22 +289,13 @@ static int ShowExtendedSystemInfo_platform_espressif() /* ** All platforms: git details */ -static int ShowExtendedSystemInfo_git() +static int ShowExtendedSystemInfo_git(void) { -#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_TAG) /* git config describe --tags --abbrev=0 */ WOLFSSL_VERSION_PRINTF("LIBWOLFSSL_VERSION_GIT_TAG = %s", @@ -290,14 +332,13 @@ static int ShowExtendedSystemInfo_git() LIBWOLFSSL_VERSION_GIT_HASH_DATE); #endif -#endif /* else not HAVE_WC_INTROSPECTION */ - return 0; + return ESP_OK; } /* ** All platforms: thread details */ -static int ShowExtendedSystemInfo_thread() +static int ShowExtendedSystemInfo_thread(void) { /* all platforms: stack high water mark check */ #if defined(SINGLE_THREADED) @@ -305,13 +346,13 @@ static int ShowExtendedSystemInfo_thread() #else WOLFSSL_VERSION_PRINTF("NOT SINGLE_THREADED"); #endif - return 0; + return ESP_OK; } /* ** All Platforms: platform details */ -static int ShowExtendedSystemInfo_platform() +static int ShowExtendedSystemInfo_platform(void) { #if defined(WOLFSSL_ESPIDF) #if defined(CONFIG_IDF_TARGET) @@ -320,44 +361,233 @@ static int ShowExtendedSystemInfo_platform() ShowExtendedSystemInfo_platform_espressif(); #endif #endif - return 0; + return ESP_OK; +} + +int esp_increment_boot_count(void) +{ + return ++_boot_count; } +int esp_current_boot_count(void) +{ + return _boot_count; +} + +/* See macro helpers above; not_defined is macro name when *not* defined */ +static int esp_ShowMacroStatus(char* s, char* not_defined) +{ + char hd1[] = "Macro Name Defined Not Defined"; + char hd2[] = "------------------------- --------- -------------"; + char msg[] = "......................... "; + /* 012345678901234567890123456789012345678901234567890 */ + /* 1 2 3 4 5 */ + size_t i = 0; + #define MAX_STATUS_NAME_LENGTH 25 + #define ESP_SMS_ENA_POS 30 + #define ESP_SMS_DIS_POS 42 + + /* save our string (s) into the space-padded message (msg) */ + while (s[i] != '\0' && msg[i] != '\0' && (i < MAX_STATUS_NAME_LENGTH)) { + msg[i] = s[i]; + i++; + } + + /* Depending on if defined, put an "x" in the appropriate column */ + if (not_defined == NULL || not_defined[0] == '\0') { + msg[ESP_SMS_ENA_POS] = 'X'; + } + else { + msg[ESP_SMS_DIS_POS] = 'X'; + } + + /* do we need a header? */ + if (esp_ShowMacroStatus_need_header) { + ESP_LOGI(TAG, "%s", hd1); + ESP_LOGI(TAG, "%s", hd2); + esp_ShowMacroStatus_need_header = 0; + } + + /* show the macro name with the "x" in the defined/not defined column */ + ESP_LOGI(TAG, "%s", msg); + return ESP_OK; +} + +/* Show some interesting settings */ +int esp_ShowHardwareAcclerationSettings(void) +{ + esp_ShowMacroStatus_need_header = 1; + esp_ShowMacroStatus("HW_MATH_ENABLED", STR_IFNDEF(HW_MATH_ENABLED)); + esp_ShowMacroStatus("RSA_LOW_MEM", STR_IFNDEF(RSA_LOW_MEM)); + esp_ShowMacroStatus("WOLFSSL_SHA224", STR_IFNDEF(WOLFSSL_SHA224)); + esp_ShowMacroStatus("WOLFSSL_SHA384", STR_IFNDEF(WOLFSSL_SHA384)); + esp_ShowMacroStatus("WOLFSSL_SHA512", STR_IFNDEF(WOLFSSL_SHA512)); + esp_ShowMacroStatus("WOLFSSL_SHA3", STR_IFNDEF(WOLFSSL_SHA3)); + esp_ShowMacroStatus("HAVE_ED25519", STR_IFNDEF(HAVE_ED25519)); + esp_ShowMacroStatus("USE_FAST_MATH", STR_IFNDEF(USE_FAST_MATH)); + esp_ShowMacroStatus("WOLFSSL_SP_MATH_ALL", STR_IFNDEF(WOLFSSL_SP_MATH_ALL)); + esp_ShowMacroStatus("WOLFSSL_SP_RISCV32", STR_IFNDEF(WOLFSSL_SP_RISCV32)); + esp_ShowMacroStatus("SP_MATH", STR_IFNDEF(SP_MATH)); + esp_ShowMacroStatus("WOLFSSL_HW_METRICS", STR_IFNDEF(WOLFSSL_HW_METRICS)); + + #ifdef USE_FAST_MATH + ESP_LOGI(TAG, "USE_FAST_MATH"); + #endif /* USE_FAST_MATH */ + + #ifdef WOLFSSL_SP_MATH_ALL + #ifdef WOLFSSL_SP_RISCV32 + ESP_LOGI(TAG, "WOLFSSL_SP_MATH_ALL + WOLFSSL_SP_RISCV32"); + #else + ESP_LOGI(TAG, "WOLFSSL_SP_MATH_ALL"); + #endif + #endif /* WOLFSSL_SP_MATH_ALL */ + + ESP_LOGI(TAG, ""); + return ESP_OK; +} /* ******************************************************************************* ** The internal, portable, but currently private ShowExtendedSystemInfo() ******************************************************************************* */ int ShowExtendedSystemInfo(void) +{ + unsigned chip_rev = -1; +#ifdef HAVE_ESP_CLK + /* esp_clk.h is private */ + int cpu_freq = 0; +#endif + + WOLFSSL_VERSION_PRINTF("Extended Version and Platform Information."); + +#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."); +#endif /* else not HAVE_WC_INTROSPECTION */ + + chip_rev = efuse_hal_chip_revision(); + ESP_LOGI(TAG, "Chip revision: v%d.%d", chip_rev / 100, chip_rev % 100); + +#ifdef HAVE_ESP_CLK + cpu_freq = esp_clk_cpu_freq(); + ESP_EARLY_LOGI(TAG, "cpu freq: %d Hz", cpu_freq); +#endif + +#if defined(SHOW_SSID_AND_PASSWORD) + ESP_LOGW(TAG, "WARNING: SSID and plain text WiFi " + "password displayed in startup logs. "); + ESP_LOGW(TAG, "Remove SHOW_SSID_AND_PASSWORD from user_settings.h " + "to disable."); +#else + ESP_LOGI(TAG, "SSID and plain text WiFi " + "password not displayed in startup logs."); + ESP_LOGI(TAG, " Define SHOW_SSID_AND_PASSWORD to enable display."); +#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 components and " + "local project [components] directory."); + WOLFSSL_VERSION_PRINTF(""); +#else + #ifdef WOLFSSL_USER_SETTINGS_DIR + { + ESP_LOGI(TAG, "Using wolfSSL user_settings.h in %s", + WOLFSSL_USER_SETTINGS_DIR); + } + #else { - WOLFSSL_VERSION_PRINTF("Extended Version and Platform Information."); + ESP_LOGW(TAG, "Warning: old cmake, user_settings.h location unknown."); + } + #endif +#endif #if defined(LIBWOLFSSL_VERSION_STRING) - WOLFSSL_VERSION_PRINTF("LIBWOLFSSL_VERSION_STRING = %s", - 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); + 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(""); + /* some interesting settings are target specific (ESP32, -C3, -S3, etc */ +#if defined(CONFIG_IDF_TARGET_ESP32) + /* ESP_RSA_MULM_BITS should be set to at least 16 for ESP32 */ + #if defined(ESP_RSA_MULM_BITS) + #if (ESP_RSA_MULM_BITS < 16) + ESP_LOGW(TAG, "Warning: ESP_RSA_MULM_BITS < 16 for ESP32"); + #endif + #else + ESP_LOGW(TAG, "Warning: ESP_RSA_MULM_BITS not defined for ESP32"); + #endif + +#elif defined(CONFIG_IDF_TARGET_ESP32C2) + ESP_LOGI(TAG, "CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ = %u MHz", + CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ + ); +#elif defined(CONFIG_IDF_TARGET_ESP32C3) + ESP_LOGI(TAG, "CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ = %u MHz", + CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ + ); + +#elif defined(CONFIG_IDF_TARGET_ESP32C6) + ESP_LOGI(TAG, "CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ = %u MHz", + CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ + ); +/* ESP_LOGI(TAG, "Xthal_have_ccount = %u", Xthal_have_ccount); */ + +#elif defined(CONFIG_IDF_TARGET_ESP32S2) + #if defined(CONFIG_ESP32S2_DEFAULT_CPU_FREQ_MHZ) + ESP_LOGI(TAG, "CONFIG_ESP32S2_DEFAULT_CPU_FREQ_MHZ = %u MHz", + CONFIG_ESP32S2_DEFAULT_CPU_FREQ_MHZ + ); + #endif + + ESP_LOGI(TAG, "Xthal_have_ccount = %u", Xthal_have_ccount); + +#elif defined(CONFIG_IDF_TARGET_ESP32S3) + #if defined(CONFIG_ESP32S3_DEFAULT_CPU_FREQ_MHZ) + ESP_LOGI(TAG, "CONFIG_ESP32S3_DEFAULT_CPU_FREQ_MHZ = %u MHz", + CONFIG_ESP32S3_DEFAULT_CPU_FREQ_MHZ + ); + #endif + + ESP_LOGI(TAG, "Xthal_have_ccount = %u", Xthal_have_ccount); +#else + #endif - ShowExtendedSystemInfo_git(); /* may be limited during active introspection */ - ShowExtendedSystemInfo_platform(); - ShowExtendedSystemInfo_thread(); - return 0; - } + /* all platforms: stack high water mark check */ +#ifdef INCLUDE_uxTaskGetStackHighWaterMark + ESP_LOGI(TAG, "Stack HWM: %d", uxTaskGetStackHighWaterMark(NULL)); +#endif + ESP_LOGI(TAG, ""); + + esp_ShowHardwareAcclerationSettings(); + ShowExtendedSystemInfo_git(); + ShowExtendedSystemInfo_platform(); + ShowExtendedSystemInfo_thread(); + + /* show number of RTC sleep boots */ + esp_increment_boot_count(); + ESP_LOGI(TAG, "Boot count: %d", esp_current_boot_count()); -WOLFSSL_LOCAL int esp_ShowExtendedSystemInfo() + return ESP_OK; +} + +int esp_ShowExtendedSystemInfo(void) { + /* Someday the ShowExtendedSystemInfo may be global. + * See https://github.com/wolfSSL/wolfssl/pull/6149 */ return ShowExtendedSystemInfo(); } @@ -366,12 +596,13 @@ WOLFSSL_LOCAL int esp_ShowExtendedSystemInfo() * Note with the right string parameters, the result can be pasted as * initialization code. */ -WOLFSSL_LOCAL int esp_show_mp_attributes(char* c, MATH_INT_T* X) +int esp_show_mp_attributes(char* c, MATH_INT_T* X) { static const char* MP_TAG = "MATH_INT_T"; - int ret = 0; + int ret = ESP_OK; + if (X == NULL) { - ret = -1; + ret = ESP_FAIL; ESP_LOGV(MP_TAG, "esp_show_mp_attributes called with X == NULL"); } else { @@ -389,15 +620,14 @@ WOLFSSL_LOCAL int esp_show_mp_attributes(char* c, MATH_INT_T* X) * Note with the right string parameters, the result can be pasted as * initialization code. */ -WOLFSSL_LOCAL int esp_show_mp(char* c, MATH_INT_T* X) +int esp_show_mp(char* c, MATH_INT_T* X) { static const char* MP_TAG = "MATH_INT_T"; int ret = MP_OKAY; int words_to_show = 0; - size_t i; if (X == NULL) { - ret = -1; + ret = ESP_FAIL; ESP_LOGV(MP_TAG, "esp_show_mp called with X == NULL"); } else { @@ -420,7 +650,7 @@ WOLFSSL_LOCAL int esp_show_mp(char* c, MATH_INT_T* X) #endif ESP_LOGI(MP_TAG, "%s:",c); esp_show_mp_attributes(c, X); - for (i = 0; i < words_to_show; i++) { + for (size_t i = 0; i < words_to_show; i++) { ESP_LOGI(MP_TAG, "%s.dp[%2d] = 0x%08x; /* %2d */ ", c, /* the supplied variable name */ i, /* the index, i for dp[%d] */ @@ -435,12 +665,10 @@ WOLFSSL_LOCAL int esp_show_mp(char* c, MATH_INT_T* X) /* Perform a full mp_cmp and binary compare. * (typically only used during debugging) */ -WOLFSSL_LOCAL int esp_mp_cmp(char* name_A, MATH_INT_T* A, char* name_B, MATH_INT_T* B) +int esp_mp_cmp(char* name_A, MATH_INT_T* A, char* name_B, MATH_INT_T* B) { int ret = MP_OKAY; - int e; - - e = memcmp(A, B, sizeof(mp_int)); + int e = memcmp(A, B, sizeof(mp_int)); if (mp_cmp(A, B) == MP_EQ) { if (e == 0) { /* we always want to be here: both esp_show_mp and binary equal! */ @@ -486,10 +714,38 @@ WOLFSSL_LOCAL int esp_mp_cmp(char* name_A, MATH_INT_T* A, char* name_B, MATH_INT name_A, name_B); } else { -#ifdef DEBUG_WOLFSSL - esp_show_mp(name_A, A); - esp_show_mp(name_B, B); -#endif + /* esp_show_mp(name_A, A); */ + /* esp_show_mp(name_B, B); */ } return ret; } + +int esp_hw_show_metrics(void) +{ +#if defined(WOLFSSL_HW_METRICS) + #if defined(WOLFSSL_ESP32_CRYPT) + esp_hw_show_sha_metrics(); + #else + ESP_LOGI(TAG, "WOLFSSL_ESP32_CRYPT"); + #endif + + #if defined(WOLFSSL_ESP32_CRYPT_RSA_PRI) + esp_hw_show_mp_metrics(); + #else + ESP_LOGI(TAG, "WOLFSSL_ESP32_CRYPT_RSA_PRI not defined," + "HW math not enabled"); + #endif + + #if defined(NO_WOLFSSL_ESP32_CRYPT_AES) + ESP_LOGI(TAG, "NO_WOLFSSL_ESP32_CRYPT_AES is defined," + "HW AES not enabled"); + #else + esp_hw_show_aes_metrics(); + #endif +#else + ESP_LOGV(TAG, "WOLFSSL_HW_METRICS is not enabled"); +#endif + return ESP_OK; +} + +#endif /* WOLFSSL_ESPIDF */ diff --git a/wolfcrypt/src/random.c b/wolfcrypt/src/random.c index 0d67d47261..cc47fab270 100644 --- a/wolfcrypt/src/random.c +++ b/wolfcrypt/src/random.c @@ -3394,7 +3394,8 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) /* Espressif ESP32 */ #include - #if defined(CONFIG_IDF_TARGET_ESP32S3) + #if defined(CONFIG_IDF_TARGET_ESP32S2) || \ + defined(CONFIG_IDF_TARGET_ESP32S3) #include #endif diff --git a/wolfcrypt/src/sha.c b/wolfcrypt/src/sha.c index 7e9bbccefa..afad7dbfdb 100644 --- a/wolfcrypt/src/sha.c +++ b/wolfcrypt/src/sha.c @@ -58,7 +58,9 @@ #include #endif +/* Assume no hash HW available until supporting HW found. */ #undef WOLFSSL_USE_ESP32_CRYPT_HASH_HW + #if defined(WOLFSSL_ESP32_CRYPT) && \ !defined(NO_WOLFSSL_ESP32_CRYPT_HASH) /* define a single keyword for simplicity & readability @@ -533,9 +535,9 @@ static WC_INLINE void AddLength(wc_Sha* sha, word32 len) /* -** wolfCrypt InitSha256 external wrapper. +** wolfCrypt InitSha external wrapper. ** -** we'll assume this is ALWAYS for a new, uninitialized sha256 +** we'll assume this is ALWAYS for a new, uninitialized sha */ int wc_InitSha_ex(wc_Sha* sha, void* heap, int devId) { @@ -569,7 +571,7 @@ int wc_InitSha_ex(wc_Sha* sha, void* heap, int devId) 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 @@ -630,21 +632,43 @@ int wc_ShaUpdate(wc_Sha* sha, const byte* data, word32 len) len -= blocksLen; if (sha->buffLen == WC_SHA_BLOCK_SIZE) { - #if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA) - ByteReverseWords(sha->buffer, sha->buffer, WC_SHA_BLOCK_SIZE); - #endif - #if defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW) if (sha->ctx.mode == ESP32_SHA_INIT) { - ESP_LOGV(TAG, "wc_ShaUpdate try hardware"); + #if defined(DEBUG_WOLFSSL_SHA_MUTEX) + { + ESP_LOGI(TAG, "wc_ShaUpdate try hardware"); + } + #endif esp_sha_try_hw_lock(&sha->ctx); } + #endif + + #if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA) + #if (defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6)) \ + && defined(WOLFSSL_ESP32_CRYPT) && \ + !defined(NO_WOLFSSL_ESP32_CRYPT_HASH) + if (esp_sha_need_byte_reversal(&sha->ctx)) + #endif + { + ByteReverseWords(sha->buffer, sha->buffer, WC_SHA_BLOCK_SIZE); + } + #endif + + #if defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW) if (sha->ctx.mode == ESP32_SHA_SW) { - ESP_LOGI(TAG, "wc_ShaUpdate process software"); + #if defined(DEBUG_WOLFSSL_SHA_MUTEX) + { + ESP_LOGI(TAG, "wc_ShaUpdate process software"); + } + #endif ret = XTRANSFORM(sha, (const byte*)local); } else { - ESP_LOGV(TAG, "wc_ShaUpdate process hardware"); + #if defined(DEBUG_WOLFSSL_SHA_MUTEX) + { + ESP_LOGI(TAG, "wc_ShaUpdate process hardware"); + } + #endif esp_sha_process(sha, (const byte*)local); } #elif defined (WOLFSSL_USE_ESP32C3_CRYPT_HASH_HW) @@ -691,14 +715,24 @@ int wc_ShaUpdate(wc_Sha* sha, const byte* data, word32 len) data += WC_SHA_BLOCK_SIZE; len -= WC_SHA_BLOCK_SIZE; - #if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA) - ByteReverseWords(local32, local32, WC_SHA_BLOCK_SIZE); - #endif - #if defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW) if (sha->ctx.mode == ESP32_SHA_INIT){ esp_sha_try_hw_lock(&sha->ctx); } + #endif + + #if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA) + #if (defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6)) && \ + defined(WOLFSSL_ESP32_CRYPT) && \ + !defined(NO_WOLFSSL_ESP32_CRYPT_HASH) + if (esp_sha_need_byte_reversal(&sha->ctx)) + #endif + { + ByteReverseWords(local32, local32, WC_SHA_BLOCK_SIZE); + } + #endif + + #if defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW) if (sha->ctx.mode == ESP32_SHA_SW){ ret = XTRANSFORM(sha, (const byte*)local32); } @@ -731,7 +765,14 @@ int wc_ShaFinalRaw(wc_Sha* sha, byte* hash) } #ifdef LITTLE_ENDIAN_ORDER - ByteReverseWords((word32*)digest, (word32*)sha->digest, WC_SHA_DIGEST_SIZE); + #if (defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6)) && \ + defined(WOLFSSL_ESP32_CRYPT) && \ + !defined(NO_WOLFSSL_ESP32_CRYPT_HASH) + if (esp_sha_need_byte_reversal(&sha->ctx)) + #endif + { + ByteReverseWords((word32*)digest, (word32*)sha->digest, WC_SHA_DIGEST_SIZE); + } XMEMCPY(hash, (byte *)&digest[0], WC_SHA_DIGEST_SIZE); #else XMEMCPY(hash, sha->digest, WC_SHA_DIGEST_SIZE); @@ -785,16 +826,25 @@ int wc_ShaFinal(wc_Sha* sha, byte* hash) XMEMSET(&local[sha->buffLen], 0, WC_SHA_BLOCK_SIZE - sha->buffLen); sha->buffLen += WC_SHA_BLOCK_SIZE - sha->buffLen; - #if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA) - ByteReverseWords(sha->buffer, sha->buffer, WC_SHA_BLOCK_SIZE); - #endif - #if defined(WOLFSSL_USE_ESP32_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); } + #endif + + #if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA) + #if (defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6)) && \ + defined(WOLFSSL_ESP32_CRYPT) && \ + !defined(NO_WOLFSSL_ESP32_CRYPT_HASH) + if (esp_sha_need_byte_reversal(&sha->ctx)) + #endif + { + ByteReverseWords(sha->buffer, sha->buffer, WC_SHA_BLOCK_SIZE); + } + #endif + #if defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW) /* 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); @@ -802,9 +852,6 @@ int wc_ShaFinal(wc_Sha* sha, byte* hash) else { ret = esp_sha_process(sha, (const byte*)local); } - #elif defined(WOLFSSL_USE_ESP32C3_CRYPT_HASH_HW) - /* The ESP32C3 is different; SW crypto here. Not yet implemented */ - ret = XTRANSFORM(sha, (const byte*)local); #else /* ** The #if defined(WOLFSSL_USE_ESP32C3_CRYPT_HASH_HW) also falls @@ -817,12 +864,25 @@ int wc_ShaFinal(wc_Sha* sha, byte* hash) } sha->buffLen = 0; - } /* (sha->buffLen > WC_SHA_PAD_SIZE) */ + } /* (sha->buffLen > WC_SHA_PAD_SIZE) */ XMEMSET(&local[sha->buffLen], 0, WC_SHA_PAD_SIZE - sha->buffLen); +#if defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW) + if (sha->ctx.mode == ESP32_SHA_INIT) { + esp_sha_try_hw_lock(&sha->ctx); + } +#endif + #if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA) - ByteReverseWords(sha->buffer, sha->buffer, WC_SHA_BLOCK_SIZE); + #if (defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6)) && \ + defined(WOLFSSL_ESP32_CRYPT) && \ + !defined(NO_WOLFSSL_ESP32_CRYPT_HASH) + if (esp_sha_need_byte_reversal(&sha->ctx)) + #endif + { /* reminder local also points to sha->buffer */ + ByteReverseWords(sha->buffer, sha->buffer, WC_SHA_BLOCK_SIZE); + } #endif /* store lengths */ @@ -841,10 +901,26 @@ int wc_ShaFinal(wc_Sha* sha, byte* hash) 2 * sizeof(word32)); #endif + +#if (defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6)) && \ + defined(WOLFSSL_ESP32_CRYPT) && !defined(NO_WOLFSSL_ESP32_CRYPT_HASH) +if (sha->ctx.mode == ESP32_SHA_HW) { + /* TODO is this the proper way to reverse endianness for the 64bit Espressif value? + * see also ByteReverseWord64() */ +#if defined(WOLFSSL_SUPER_VERBOSE_DEBUG) + ESP_LOGV(TAG, "Start: Reverse PAD SIZE Endianness."); +#endif + ByteReverseWords(&sha->buffer[WC_SHA_PAD_SIZE/sizeof(word32)], /* out */ + &sha->buffer[WC_SHA_PAD_SIZE/sizeof(word32)], /* in */ + 2 * sizeof(word32) /* byte count to reverse */ + ); +#if defined(WOLFSSL_SUPER_VERBOSE_DEBUG) + ESP_LOGV(TAG, "End: Reverse PAD SIZE Endianness."); +#endif +} /* end if (sha->ctx.mode == ESP32_SHA_HW) */ +#endif + #if defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW) - if (sha->ctx.mode == ESP32_SHA_INIT) { - esp_sha_try_hw_lock(&sha->ctx); - } if (sha->ctx.mode == ESP32_SHA_SW) { ret = XTRANSFORM(sha, (const byte*)local); } @@ -860,7 +936,14 @@ int wc_ShaFinal(wc_Sha* sha, byte* hash) #endif #ifdef LITTLE_ENDIAN_ORDER - ByteReverseWords(sha->digest, sha->digest, WC_SHA_DIGEST_SIZE); + #if (defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6)) && \ + defined(WOLFSSL_ESP32_CRYPT) && \ + !defined(NO_WOLFSSL_ESP32_CRYPT_HASH) + if (esp_sha_need_byte_reversal(&sha->ctx)) + #endif + { + ByteReverseWords(sha->digest, sha->digest, WC_SHA_DIGEST_SIZE); + } #endif XMEMCPY(hash, (byte *)&sha->digest[0], WC_SHA_DIGEST_SIZE); @@ -869,7 +952,6 @@ int wc_ShaFinal(wc_Sha* sha, byte* hash) * which may cause fall back to SW if HW is busy. we do not return result * of initSha here */ (void)InitSha(sha); /* reset state */ - return ret; } @@ -906,6 +988,10 @@ void wc_ShaFree(wc_Sha* sha) if (sha == NULL) return; +#if defined(WOLFSSL_ESP32) && !defined(NO_WOLFSSL_ESP32_CRYPT_HASH) + esp_sha_release_unfinished_lock(&sha->ctx); +#endif + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA) wolfAsync_DevCtxFree(&sha->asyncDev, WOLFSSL_ASYNC_MARKER_SHA); #endif /* WOLFSSL_ASYNC_CRYPT */ diff --git a/wolfcrypt/src/sha256.c b/wolfcrypt/src/sha256.c index 89c33bc718..54b08f091d 100644 --- a/wolfcrypt/src/sha256.c +++ b/wolfcrypt/src/sha256.c @@ -701,6 +701,54 @@ static int InitSha256(wc_Sha256* sha256) #define NEED_SOFT_SHA256 /* + * we'll set the digest at the last minute, + * just before computing hash. + * + * Reminder that ESP32-C3 does NOT need initial digest. + * + * see page 337 of C3 spec: 16.4.1.3 Setting the Initial Hash Value + * + * "Before hash task begins for any secure hash algorithms, the initial + * Hash value H(0) must be set based on different algorithms. However, + * the SHA accelerator uses the initial Hash values (constant C) stored + * in the hardware for hash tasks" + */ + static int set_default_digest256(wc_Sha256* sha256) + { + return 0; /* TODO not used? */ + int ret = 0; +#ifndef NO_WOLFSSL_ESP32_CRYPT_HASH_SHA256 + + if (sha256->ctx.mode == ESP32_SHA_SW) { + ret = 1; + } +#endif + + /* when not ESP32-C3, we'll need digest for SW or HW */ + #if !defined(CONFIG_IDF_TARGET_ESP32C3) && \ + !defined(CONFIG_IDF_TARGET_ESP32C6) + ret = 1; + #endif + +#ifndef NO_WOLFSSL_ESP32_CRYPT_HASH_SHA256 + if ((ret == 1) && (sha256->ctx.isfirstblock == 1)) { + XMEMSET(sha256->digest, 0, sizeof(sha256->digest)); + sha256->digest[0] = 0x6A09E667L; + sha256->digest[1] = 0xBB67AE85L; + sha256->digest[2] = 0x3C6EF372L; + sha256->digest[3] = 0xA54FF53AL; + sha256->digest[4] = 0x510E527FL; + sha256->digest[5] = 0x9B05688CL; + sha256->digest[6] = 0x1F83D9ABL; + sha256->digest[7] = 0x5BE0CD19L; + } +#endif + return ret; + } + + /* + ** An Espressif-specific InitSha256() + ** ** soft SHA needs initialization digest, but HW does not. */ static int InitSha256(wc_Sha256* sha256) @@ -711,6 +759,9 @@ static int InitSha256(wc_Sha256* sha256) return BAD_FUNC_ARG; } + /* we may or may not need initial digest. + * always needed for SW-only. + * See set_default_digest256() for HW/SW */ sha256->digest[0] = 0x6A09E667L; sha256->digest[1] = 0xBB67AE85L; sha256->digest[2] = 0x3C6EF372L; @@ -724,13 +775,14 @@ static int InitSha256(wc_Sha256* sha256) sha256->loLen = 0; sha256->hiLen = 0; +#ifndef NO_WOLFSSL_ESP32_CRYPT_HASH_SHA256 ret = esp_sha_init(&(sha256->ctx), WC_HASH_TYPE_SHA256); - +#endif return ret; } /* - ** wolfCrypt InitSha256 external wrapper. + ** An Espressif-specific wolfCrypt InitSha256 external wrapper. ** ** we'll assume this is ALWAYS for a new, uninitialized sha256 */ @@ -742,12 +794,14 @@ static int InitSha256(wc_Sha256* sha256) } #ifdef WOLFSSL_USE_ESP32_CRYPT_HASH_HW +#ifndef NO_WOLFSSL_ESP32_CRYPT_HASH_SHA256 /* 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; +#endif #endif return InitSha256(sha256); @@ -1051,33 +1105,62 @@ static int InitSha256(wc_Sha256* sha256) len -= blocksLen; if (sha256->buffLen == WC_SHA256_BLOCK_SIZE) { + #if defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW) && \ + !defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA256) + if (sha256->ctx.mode == ESP32_SHA_INIT) { + ESP_LOGV(TAG, "Sha256Update try hardware"); + esp_sha_try_hw_lock(&sha256->ctx); + } + set_default_digest256(sha256); + #endif + + #if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA) #if defined(WOLFSSL_X86_64_BUILD) && \ defined(USE_INTEL_SPEEDUP) && \ (defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2)) if (!IS_INTEL_AVX1(intel_flags) && !IS_INTEL_AVX2(intel_flags)) #endif + #if (defined(CONFIG_IDF_TARGET_ESP32C3) || \ + defined(CONFIG_IDF_TARGET_ESP32C6)) && \ + defined(WOLFSSL_ESP32_CRYPT) && \ + !defined(NO_WOLFSSL_ESP32_CRYPT_HASH) && \ + !defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA256) + if (esp_sha_need_byte_reversal(&sha256->ctx)) + #endif { ByteReverseWords(sha256->buffer, sha256->buffer, WC_SHA256_BLOCK_SIZE); } #endif - #if defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW) - if (sha256->ctx.mode == ESP32_SHA_INIT) { - ESP_LOGV(TAG, "Sha256Update try hardware"); - esp_sha_try_hw_lock(&sha256->ctx); - } + #if defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW) && \ + !defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA256) if (sha256->ctx.mode == ESP32_SHA_SW) { - ESP_LOGV(TAG, "Sha256Update process software"); + #if defined(DEBUG_WOLFSSL_SHA_MUTEX) + { + ESP_LOGI(TAG, "Sha256Update process software"); + } + #endif + #ifdef WOLFSSL_HW_METRICS + { + /* Track of # SW during transforms during active HW */ + esp_sw_sha256_count_add(); + } + #endif /* WOLFSSL_HW_METRICS */ ret = XTRANSFORM(sha256, (const byte*)local); } else { - ESP_LOGV(TAG, "Sha256Update process hardware"); + #if defined(DEBUG_WOLFSSL_SHA_MUTEX) + { + ESP_LOGI(TAG, "Sha256Update process hardware"); + } + #endif esp_sha256_process(sha256, (const byte*)local); } #else + /* Always SW */ ret = XTRANSFORM(sha256, (const byte*)local); #endif @@ -1135,8 +1218,22 @@ static int InitSha256(wc_Sha256* sha256) data += WC_SHA256_BLOCK_SIZE; len -= WC_SHA256_BLOCK_SIZE; + #if defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW) && \ + !defined( NO_WOLFSSL_ESP32_CRYPT_HASH_SHA256) + if (sha256->ctx.mode == ESP32_SHA_INIT){ + ESP_LOGV(TAG, "Sha256Update try hardware loop"); + esp_sha_try_hw_lock(&sha256->ctx); + } + #endif #if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA) + #if (defined(CONFIG_IDF_TARGET_ESP32C3) || \ + defined(CONFIG_IDF_TARGET_ESP32C6)) && \ + defined(WOLFSSL_ESP32_CRYPT) && \ + !defined(NO_WOLFSSL_ESP32_CRYPT_HASH) && \ + !defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA256) + if (esp_sha_need_byte_reversal(&sha256->ctx)) + #endif #if defined(WOLFSSL_X86_64_BUILD) && \ defined(USE_INTEL_SPEEDUP) && \ (defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2)) @@ -1147,11 +1244,8 @@ static int InitSha256(wc_Sha256* sha256) } #endif - #if defined(WOLFSSL_USE_ESP32_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 defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW) && \ + !defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA256) if (sha256->ctx.mode == ESP32_SHA_SW) { ESP_LOGV(TAG, "Sha256Update process software loop"); ret = XTRANSFORM(sha256, (const byte*)local32); @@ -1243,7 +1337,21 @@ static int InitSha256(wc_Sha256* sha256) WC_SHA256_BLOCK_SIZE - sha256->buffLen); sha256->buffLen += WC_SHA256_BLOCK_SIZE - sha256->buffLen; + #if defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW) && \ + !defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA256) + if (sha256->ctx.mode == ESP32_SHA_INIT) { + esp_sha_try_hw_lock(&sha256->ctx); + } + #endif + #if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA) + #if (defined(CONFIG_IDF_TARGET_ESP32C3) || \ + defined(CONFIG_IDF_TARGET_ESP32C6)) && \ + defined(WOLFSSL_ESP32_CRYPT) && \ + !defined(NO_WOLFSSL_ESP32_CRYPT_HASH) && \ + !defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA256) + if (esp_sha_need_byte_reversal(&sha256->ctx)) + #endif #if defined(WOLFSSL_X86_64_BUILD) && defined(USE_INTEL_SPEEDUP) && \ (defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2)) if (!IS_INTEL_AVX1(intel_flags) && !IS_INTEL_AVX2(intel_flags)) @@ -1254,7 +1362,8 @@ static int InitSha256(wc_Sha256* sha256) } #endif - #if defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW) + #if defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW) && \ + !defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA256) if (sha256->ctx.mode == ESP32_SHA_INIT) { esp_sha_try_hw_lock(&sha256->ctx); } @@ -1275,13 +1384,27 @@ static int InitSha256(wc_Sha256* sha256) XMEMSET(&local[sha256->buffLen], 0, WC_SHA256_PAD_SIZE - sha256->buffLen); - /* put lengths in bits */ + /* put 64 bit length in separate 32 bit parts */ sha256->hiLen = (sha256->loLen >> (8 * sizeof(sha256->loLen) - 3)) + (sha256->hiLen << 3); sha256->loLen = sha256->loLen << 3; + #if defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW) && \ + !defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA256) + if (sha256->ctx.mode == ESP32_SHA_INIT) { + esp_sha_try_hw_lock(&sha256->ctx); + } + #endif + /* store lengths */ #if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA) + #if (defined(CONFIG_IDF_TARGET_ESP32C3) || \ + defined(CONFIG_IDF_TARGET_ESP32C6)) && \ + defined(WOLFSSL_ESP32_CRYPT) && \ + !defined(NO_WOLFSSL_ESP32_CRYPT_HASH) && \ + !defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA256) + if (esp_sha_need_byte_reversal(&sha256->ctx)) + #endif #if defined(WOLFSSL_X86_64_BUILD) && defined(USE_INTEL_SPEEDUP) && \ (defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2)) if (!IS_INTEL_AVX1(intel_flags) && !IS_INTEL_AVX2(intel_flags)) @@ -1291,11 +1414,33 @@ static int InitSha256(wc_Sha256* sha256) WC_SHA256_BLOCK_SIZE); } #endif - /* ! length ordering dependent on digest endian type ! */ + /* ! 64-bit length ordering dependent on digest endian type ! */ XMEMCPY(&local[WC_SHA256_PAD_SIZE], &sha256->hiLen, sizeof(word32)); XMEMCPY(&local[WC_SHA256_PAD_SIZE + sizeof(word32)], &sha256->loLen, sizeof(word32)); + /* Only the ESP32-C3 with HW enabled may need pad size byte order reversal + * depending on HW or SW mode */ + #if (defined(CONFIG_IDF_TARGET_ESP32C3) || \ + defined(CONFIG_IDF_TARGET_ESP32C6)) && \ + defined(WOLFSSL_ESP32_CRYPT) && \ + !defined(NO_WOLFSSL_ESP32_CRYPT_HASH) && \ + !defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA256) + if (sha256->ctx.mode == ESP32_SHA_HW) { + #if defined(WOLFSSL_SUPER_VERBOSE_DEBUG) + ESP_LOGV(TAG, "Start: Reverse PAD SIZE Endianness."); + #endif + ByteReverseWords( + &sha256->buffer[WC_SHA256_PAD_SIZE / sizeof(word32)], /* out */ + &sha256->buffer[WC_SHA256_PAD_SIZE / sizeof(word32)], /* in */ + 2 * sizeof(word32) /* byte count to reverse */ + ); + #if defined(WOLFSSL_SUPER_VERBOSE_DEBUG) + ESP_LOGV(TAG, "End: Reverse PAD SIZE Endianness."); + #endif + } /* end if (sha256->ctx.mode == ESP32_SHA_HW) */ + #endif + #if defined(FREESCALE_MMCAU_SHA) || \ (defined(WOLFSSL_X86_64_BUILD) && defined(USE_INTEL_SPEEDUP) && \ (defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2))) @@ -1312,10 +1457,13 @@ static int InitSha256(wc_Sha256* sha256) } #endif - #if defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW) + #if defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW) && \ + !defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA256) if (sha256->ctx.mode == ESP32_SHA_INIT) { esp_sha_try_hw_lock(&sha256->ctx); } + /* depending on architecture and ctx.mode value + * we may or may not need default digest */ if (sha256->ctx.mode == ESP32_SHA_SW) { ret = XTRANSFORM(sha256, (const byte*)local); } @@ -1342,8 +1490,18 @@ static int InitSha256(wc_Sha256* sha256) } #ifdef LITTLE_ENDIAN_ORDER - ByteReverseWords((word32*)digest, (word32*)sha256->digest, - WC_SHA256_DIGEST_SIZE); + #if (defined(CONFIG_IDF_TARGET_ESP32C3) || \ + defined(CONFIG_IDF_TARGET_ESP32C6)) && \ + defined(WOLFSSL_ESP32_CRYPT) && \ + !defined(NO_WOLFSSL_ESP32_CRYPT_HASH) && \ + !defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA256) + if (esp_sha_need_byte_reversal(&sha256->ctx)) + #endif + { + ByteReverseWords((word32*)digest, + (word32*)sha256->digest, + WC_SHA256_DIGEST_SIZE); + } XMEMCPY(hash, digest, WC_SHA256_DIGEST_SIZE); #else XMEMCPY(hash, sha256->digest, WC_SHA256_DIGEST_SIZE); @@ -1387,7 +1545,16 @@ static int InitSha256(wc_Sha256* sha256) } #if defined(LITTLE_ENDIAN_ORDER) - ByteReverseWords(sha256->digest, sha256->digest, WC_SHA256_DIGEST_SIZE); + #if (defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6)) && \ + defined(WOLFSSL_ESP32_CRYPT) && \ + !defined(NO_WOLFSSL_ESP32_CRYPT_HASH) && \ + !defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA256) + if (esp_sha_need_byte_reversal(&sha256->ctx)) + #endif + { + ByteReverseWords(sha256->digest, sha256->digest, + WC_SHA256_DIGEST_SIZE); + } #endif XMEMCPY(hash, sha256->digest, WC_SHA256_DIGEST_SIZE); @@ -1560,9 +1727,11 @@ static int InitSha256(wc_Sha256* sha256) sha224->used = 0; #endif - #if defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW) - /* not to be confused with HAS512_224 */ - sha224->ctx.mode = ESP32_SHA_SW; /* no SHA224 HW, so always SW */ + #if defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW) && \ + (!defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA256) || \ + !defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA224)) + /* not to be confused with SHAS512_224 */ + ret = esp_sha_init(&(sha224->ctx), WC_HASH_TYPE_SHA224); #endif return ret; @@ -1583,14 +1752,19 @@ static int InitSha256(wc_Sha256* sha256) sha224->W = NULL; #endif - #ifdef WOLFSSL_USE_ESP32_CRYPT_HASH_HW + #if defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW) + #if defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA224) /* 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; + sha224->ctx.mode = ESP32_SHA_SW; + #else + /* We know this is a fresh, uninitialized item, so set to INIT */ + sha224->ctx.mode = ESP32_SHA_INIT; + #endif #endif ret = InitSha224(sha224); @@ -1608,7 +1782,9 @@ static int InitSha256(wc_Sha256* sha256) ret = wc_CAAM_HashInit(&sha224->hndl, &sha224->ctx, WC_HASH_TYPE_SHA224); #endif - #ifdef WOLFSSL_USE_ESP32_CRYPT_HASH_HW + #if defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW) && \ + (!defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA256) || \ + !defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA224)) if (sha224->ctx.mode != ESP32_SHA_INIT) { ESP_LOGV("SHA224", "Set ctx mode from prior value: " "%d", sha224->ctx.mode); @@ -1636,7 +1812,9 @@ static int InitSha256(wc_Sha256* sha256) } #endif /* WOLFSSL_ASYNC_CRYPT */ - #if defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW) + #if defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW) && \ + (defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA256) || \ + defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA224)) sha224->ctx.mode = ESP32_SHA_SW; /* no SHA224 HW, so always SW */ #endif @@ -1662,8 +1840,11 @@ static int InitSha256(wc_Sha256* sha256) } #endif /* WOLFSSL_ASYNC_CRYPT */ - #if defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW) - sha224->ctx.mode = ESP32_SHA_SW; /* no SHA224 HW, so always SW */ + #if defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW) && \ + (!defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA256) || \ + !defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA224)) + + /* nothing enabled here for C3 success */ #endif ret = Sha256Final((wc_Sha256*)sha224); @@ -1671,7 +1852,18 @@ static int InitSha256(wc_Sha256* sha256) return ret; #if defined(LITTLE_ENDIAN_ORDER) - ByteReverseWords(sha224->digest, sha224->digest, WC_SHA224_DIGEST_SIZE); + #if (defined(CONFIG_IDF_TARGET_ESP32C3) || \ + defined(CONFIG_IDF_TARGET_ESP32C6)) && \ + defined(WOLFSSL_ESP32_CRYPT) && \ + (!defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA256) || \ + !defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA224)) + if (esp_sha_need_byte_reversal(&sha224->ctx)) + #endif + { + ByteReverseWords(sha224->digest, + sha224->digest, + WC_SHA224_DIGEST_SIZE); + } #endif XMEMCPY(hash, sha224->digest, WC_SHA224_DIGEST_SIZE); @@ -1724,8 +1916,8 @@ static int InitSha256(wc_Sha256* sha256) #endif ForceZero(sha224, sizeof(*sha224)); } -#endif /* WOLFSSL_SHA224 */ -#endif /* !defined(WOLFSSL_HAVE_PSA) || defined(WOLFSSL_PSA_NO_HASH) */ +#endif /* !defined(WOLFSSL_HAVE_PSA) || defined(WOLFSSL_PSA_NO_HASH) */ +#endif /* WOLFSSL_SHA224 */ int wc_InitSha256(wc_Sha256* sha256) @@ -1746,6 +1938,12 @@ void wc_Sha256Free(wc_Sha256* sha256) if (sha256 == NULL) return; +#if defined(WOLFSSL_ESP32) && \ + !defined(NO_WOLFSSL_ESP32_CRYPT_HASH) && \ + !defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA256) + esp_sha_release_unfinished_lock(&sha256->ctx); +#endif + #ifdef WOLFSSL_SMALL_STACK_CACHE if (sha256->W != NULL) { ForceZero(sha256->W, sizeof(word32) * WC_SHA256_BLOCK_SIZE); @@ -1810,7 +2008,9 @@ void wc_Sha256Free(wc_Sha256* sha256) #endif /* Espressif embedded hardware acceleration specific: */ -#if defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW) +#if defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW) && \ + !defined(NO_WOLFSSL_ESP32_CRYPT_HASH) && \ + !defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA256) if (sha256->ctx.lockDepth > 0) { /* probably due to unclean shutdown, error, or other problem. * @@ -1827,7 +2027,7 @@ void wc_Sha256Free(wc_Sha256* sha256) } #endif ForceZero(sha256, sizeof(*sha256)); -} +} /* wc_Sha256Free */ #endif /* !defined(WOLFSSL_HAVE_PSA) || defined(WOLFSSL_PSA_NO_HASH) */ #ifdef WOLFSSL_HASH_KEEP @@ -1922,8 +2122,13 @@ int wc_Sha224_Grow(wc_Sha224* sha224, const byte* in, int inSz) ret = wolfAsync_DevCopy(&src->asyncDev, &dst->asyncDev); #endif - #if defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW) - ret = esp_sha224_ctx_copy(src, dst); + #if defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW) && \ + (!defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA256) || \ + !defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA224)) + /* regardless of any other settings, there's no SHA-224 HW on ESP32 */ + #ifndef CONFIG_IDF_TARGET_ESP32 + ret = esp_sha224_ctx_copy(src, dst); + #endif #endif #ifdef WOLFSSL_HASH_FLAGS @@ -2061,7 +2266,8 @@ int wc_Sha256Copy(wc_Sha256* src, wc_Sha256* dst) ret = wc_Pic32HashCopy(&src->cache, &dst->cache); #endif -#if defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW) +#if defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW) && \ + !defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA256) esp_sha256_ctx_copy(src, dst); #endif diff --git a/wolfcrypt/src/sha512.c b/wolfcrypt/src/sha512.c index 0ef343652a..c69681621e 100644 --- a/wolfcrypt/src/sha512.c +++ b/wolfcrypt/src/sha512.c @@ -32,12 +32,12 @@ /* determine if we are using Espressif SHA hardware acceleration */ #undef WOLFSSL_USE_ESP32_CRYPT_HASH_HW -#if defined(WOLFSSL_ESP32_CRYPT) && \ - !defined(NO_WOLFSSL_ESP32_CRYPT_HASH) - /* define a single keyword for simplicity & readability +#if defined(WOLFSSL_ESP32_CRYPT) && !defined(NO_WOLFSSL_ESP32_CRYPT_HASH) + #include "sdkconfig.h" + /* Define a single keyword for simplicity & readability. * - * by default the HW acceleration is on for ESP32-WROOM32 - * but individual components can be turned off. + * By default the HW acceleration is on for ESP32 Chipsets, + * but individual components can be turned off. See user_settings.h */ #define WOLFSSL_USE_ESP32_CRYPT_HASH_HW static const char* TAG = "wc_sha_512"; @@ -214,7 +214,8 @@ static int InitSha512(wc_Sha512* sha512) sha512->loLen = 0; sha512->hiLen = 0; -#if defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW) +#if defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW) && \ + !defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA512) /* HW needs to be carefully initialized, taking into account soft copy. ** If already in use; copy may revert to SW as needed. */ @@ -254,7 +255,8 @@ static int InitSha512_224(wc_Sha512* sha512) sha512->loLen = 0; sha512->hiLen = 0; -#if defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW) +#if defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW) && \ + !defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA512) /* HW needs to be carefully initialized, taking into account soft copy. ** If already in use; copy may revert to SW as needed. ** @@ -296,7 +298,8 @@ static int InitSha512_256(wc_Sha512* sha512) sha512->loLen = 0; sha512->hiLen = 0; -#if defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW) +#if defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW) && \ + !defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA512) /* HW needs to be carefully initialized, taking into account soft copy. ** If already in use; copy may revert to SW as needed. ** @@ -536,7 +539,8 @@ static int InitSha512_Family(wc_Sha512* sha512, void* heap, int devId, int wc_InitSha512_ex(wc_Sha512* sha512, void* heap, int devId) { -#if defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW) +#if defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW) && \ + !defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA512) if (sha512->ctx.mode != ESP32_SHA_INIT) { ESP_LOGV(TAG, "Set ctx mode from prior value: " "%d", sha512->ctx.mode); @@ -552,7 +556,8 @@ 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_ESP32_CRYPT_HASH_HW +#if defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW) && \ + !defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA512) /* No SHA512/224 HW support is available, set to SW. */ sha512->ctx.mode = ESP32_SHA_SW; /* no SHA224 HW, so always SW */ #endif @@ -564,7 +569,8 @@ 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_ESP32_CRYPT_HASH_HW +#if defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW) && \ + !defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA512) /* No SHA512/256 HW support is available on ESP32, set to SW. */ sha512->ctx.mode = ESP32_SHA_SW; #endif @@ -756,14 +762,16 @@ static WC_INLINE int Sha512Update(wc_Sha512* sha512, const byte* data, word32 le #endif { #if !defined(WOLFSSL_ESP32_CRYPT) || \ - defined(NO_WOLFSSL_ESP32_CRYPT_HASH) + defined(NO_WOLFSSL_ESP32_CRYPT_HASH) || \ + defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA512) ByteReverseWords64(sha512->buffer, sha512->buffer, WC_SHA512_BLOCK_SIZE); #endif } #endif #if !defined(WOLFSSL_ESP32_CRYPT) || \ - defined(NO_WOLFSSL_ESP32_CRYPT_HASH) + defined(NO_WOLFSSL_ESP32_CRYPT_HASH) || \ + defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA512) ret = Transform_Sha512(sha512); #else if(sha512->ctx.mode == ESP32_SHA_INIT) { @@ -829,12 +837,14 @@ static WC_INLINE int Sha512Update(wc_Sha512* sha512, const byte* data, word32 le data += WC_SHA512_BLOCK_SIZE; len -= WC_SHA512_BLOCK_SIZE; #if !defined(WOLFSSL_ESP32_CRYPT) || \ - defined(NO_WOLFSSL_ESP32_CRYPT_HASH) + defined(NO_WOLFSSL_ESP32_CRYPT_HASH) || \ + defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA512) ByteReverseWords64(sha512->buffer, sha512->buffer, WC_SHA512_BLOCK_SIZE); #endif #if !defined(WOLFSSL_ESP32_CRYPT) || \ - defined(NO_WOLFSSL_ESP32_CRYPT_HASH) + defined(NO_WOLFSSL_ESP32_CRYPT_HASH) || \ + defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA512) ret = Transform_Sha512(sha512); #else if(sha512->ctx.mode == ESP32_SHA_INIT) { @@ -938,14 +948,16 @@ static WC_INLINE int Sha512Final(wc_Sha512* sha512) { #if !defined(WOLFSSL_ESP32_CRYPT) || \ - defined(NO_WOLFSSL_ESP32_CRYPT_HASH) + defined(NO_WOLFSSL_ESP32_CRYPT_HASH) || \ + defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA512) ByteReverseWords64(sha512->buffer,sha512->buffer, WC_SHA512_BLOCK_SIZE); #endif } #endif /* LITTLE_ENDIAN_ORDER */ - #if defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW) + #if defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW) && \ + !defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA512) if (sha512->ctx.mode == ESP32_SHA_INIT) { esp_sha_try_hw_lock(&sha512->ctx); } @@ -980,14 +992,16 @@ static WC_INLINE int Sha512Final(wc_Sha512* sha512) if (!IS_INTEL_AVX1(intel_flags) && !IS_INTEL_AVX2(intel_flags)) #endif #if !defined(WOLFSSL_ESP32_CRYPT) || \ - defined(NO_WOLFSSL_ESP32_CRYPT_HASH) + defined(NO_WOLFSSL_ESP32_CRYPT_HASH) || \ + defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA512) ByteReverseWords64(sha512->buffer, sha512->buffer, WC_SHA512_PAD_SIZE); #endif #endif /* ! length ordering dependent on digest endian type ! */ #if !defined(WOLFSSL_ESP32_CRYPT) || \ - defined(NO_WOLFSSL_ESP32_CRYPT_HASH) + defined(NO_WOLFSSL_ESP32_CRYPT_HASH) || \ + defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA512) sha512->buffer[WC_SHA512_BLOCK_SIZE / sizeof(word64) - 2] = sha512->hiLen; sha512->buffer[WC_SHA512_BLOCK_SIZE / sizeof(word64) - 1] = sha512->loLen; #endif @@ -1001,7 +1015,8 @@ static WC_INLINE int Sha512Final(wc_Sha512* sha512) #endif #if !defined(WOLFSSL_ESP32_CRYPT) || \ - defined(NO_WOLFSSL_ESP32_CRYPT_HASH) + defined(NO_WOLFSSL_ESP32_CRYPT_HASH) || \ + defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA512) ret = Transform_Sha512(sha512); #else if(sha512->ctx.mode == ESP32_SHA_INIT) { @@ -1136,6 +1151,12 @@ void wc_Sha512Free(wc_Sha512* sha512) if (sha512 == NULL) return; +#if defined(WOLFSSL_ESP32) && \ + !defined(NO_WOLFSSL_ESP32_CRYPT_HASH) && \ + !defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA512) + esp_sha_release_unfinished_lock(&sha512->ctx); +#endif + #ifdef WOLFSSL_SMALL_STACK_CACHE if (sha512->W != NULL) { ForceZero(sha512->W, sizeof(word64) * 16); @@ -1291,7 +1312,8 @@ static int InitSha384(wc_Sha384* sha384) sha384->loLen = 0; sha384->hiLen = 0; -#if defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW) +#if defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW) && \ + !defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA384) /* 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); @@ -1417,7 +1439,8 @@ int wc_InitSha384_ex(wc_Sha384* sha384, void* heap, int devId) sha384->devId = devId; sha384->devCtx = NULL; #endif -#if defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW) +#if defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW) && \ + !defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA384) if (sha384->ctx.mode != ESP32_SHA_INIT) { ESP_LOGV(TAG, "Set ctx mode from prior value: " "%d", sha384->ctx.mode); @@ -1465,6 +1488,11 @@ void wc_Sha384Free(wc_Sha384* sha384) if (sha384 == NULL) return; +#if defined(WOLFSSL_ESP32) && !defined(NO_WOLFSSL_ESP32_CRYPT_HASH) && \ + !defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA384) + esp_sha_release_unfinished_lock(&sha384->ctx); +#endif + #ifdef WOLFSSL_SMALL_STACK_CACHE if (sha384->W != NULL) { ForceZero(sha384->W, sizeof(word64) * 16); @@ -1581,9 +1609,23 @@ int wc_Sha512Copy(wc_Sha512* src, wc_Sha512* dst) #endif #if defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW) + #if defined(CONFIG_IDF_TARGET_ESP32) if (ret == 0) { ret = esp_sha512_ctx_copy(src, dst); } + #elif defined(CONFIG_IDF_TARGET_ESP32C3) || \ + defined(CONFIG_IDF_TARGET_ESP32C6) + ESP_LOGV(TAG, "No SHA-512 HW on the ESP32-C3"); + #elif defined(CONFIG_IDF_TARGET_ESP32S2) || \ + defined(CONFIG_IDF_TARGET_ESP32S3) + if (ret == 0) { + ret = esp_sha512_ctx_copy(src, dst); + } + #else + ESP_LOGW(TAG, "No SHA384 HW or not yet implemented for %s", + CONFIG_IDF_TARGET); + #endif + #endif #ifdef WOLFSSL_HASH_FLAGS @@ -1849,7 +1891,18 @@ int wc_Sha384Copy(wc_Sha384* src, wc_Sha384* dst) #endif #if defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW) - esp_sha384_ctx_copy(src, dst); + #if defined(CONFIG_IDF_TARGET_ESP32) + esp_sha384_ctx_copy(src, dst); + #elif defined(CONFIG_IDF_TARGET_ESP32C3) || \ + defined(CONFIG_IDF_TARGET_ESP32C6) + ESP_LOGV(TAG, "No SHA-384 HW on the ESP32-C3"); + #elif defined(CONFIG_IDF_TARGET_ESP32S2) || \ + defined(CONFIG_IDF_TARGET_ESP32S3) + esp_sha384_ctx_copy(src, dst); + #else + ESP_LOGW(TAG, "No SHA384 HW or not yet implemented for %s", + CONFIG_IDF_TARGET); + #endif #endif #ifdef HAVE_ARIA diff --git a/wolfcrypt/src/tfm.c b/wolfcrypt/src/tfm.c index 8f2881afb1..c2937d2b17 100644 --- a/wolfcrypt/src/tfm.c +++ b/wolfcrypt/src/tfm.c @@ -79,9 +79,9 @@ #undef WOLFSSL_ESP32_CRYPT_RSA_PRI_MULMOD #endif - /* Note with HW there's a EPS_RSA_EXPT_XBTIS setting + /* Note with HW there's a ESP_RSA_EXPT_XBITS setting * as for some small numbers, SW may be faster. - * See ESP_LOGV messages for EPS_RSA_EXPT_XBTIS values. */ + * See ESP_LOGV messages for ESP_RSA_EXPT_XBITS values. */ #endif /* WOLFSSL_ESP32_CRYPT_RSA_PRI */ @@ -3428,6 +3428,36 @@ int fp_sqr(fp_int *A, fp_int *B) goto clean; } +#if defined(WOLFSSL_ESP32_CRYPT_RSA_PRI_MP_MUL) + if (esp_hw_validation_active()) { + ESP_LOGV(TAG, "Skipping call to esp_mp_mul " + "during active validation."); + } + else { + err = esp_mp_mul(A, A, B); /* HW accelerated multiply */ + switch (err) { + case MP_OKAY: + goto clean; /* success */ + break; + + case WC_HW_WAIT_E: /* MP_HW_BUSY math HW busy, fall back */ + case MP_HW_FALLBACK: /* forced fallback from HW to SW */ + case MP_HW_VALIDATION_ACTIVE: /* use SW to compare to HW */ + /* fall back to software, below */ + break; + + default: + /* Once we've failed, exit without trying to continue. + * We may have mangled operands: (e.g. Z = X * Z) + * Future implementation may consider saving operands, + * but errors should never occur. */ + goto clean; /* error */ + break; + } + } + /* fall through to software calcs */ +#endif /* WOLFSSL_ESP32_CRYPT_RSA_PRI_MP_MUL */ + #if defined(TFM_SQR3) && FP_SIZE >= 6 if (y <= 3) { err = fp_sqr_comba3(A,B); diff --git a/wolfssl/wolfcrypt/port/Espressif/esp32-crypt.h b/wolfssl/wolfcrypt/port/Espressif/esp32-crypt.h index 96c20f5cee..bf938383d2 100644 --- a/wolfssl/wolfcrypt/port/Espressif/esp32-crypt.h +++ b/wolfssl/wolfcrypt/port/Espressif/esp32-crypt.h @@ -22,10 +22,12 @@ #define __ESP32_CRYPT_H__ +#include /* references user_settings.h */ + +#if defined(WOLFSSL_ESPIDF) /* Entire file is only for Espressif EDP-IDF */ #include "sdkconfig.h" /* ensure ESP-IDF settings are available everywhere */ /* wolfSSL */ -#include /* references user_settings.h */ #include #include /* for MATH_INT_T */ @@ -42,54 +44,76 @@ * WC_HW_WAIT_E - waited too long for HW, fall back to SW */ -/* exit code only used in Espressif port */ +/* Exit codes only used in Espressif port: */ +enum { + ESP_MP_HW_FALLBACK = (WC_LAST_E - 2), + ESP_MP_HW_VALIDATION_ACTIVE = (WC_LAST_E - 3) +}; /* MP_HW_FALLBACK: signal to caller to fall back to SW for math: * algorithm not supported in SW * known state needing only SW, (e.g. ctx copy) - * any other reason to force SW */ -#define MP_HW_FALLBACK (-108) + * any other reason to force SW (was -108)*/ +#define MP_HW_FALLBACK ESP_MP_HW_FALLBACK /* MP_HW_VALIDATION_ACTIVE this is informative only: * typically also means "MP_HW_FALLBACK": fall back to SW. * optional HW validation active, so compute in SW to compare. - * fall back to SW, typically only used during debugging + * fall back to SW, typically only used during debugging. (was -109) */ -#define MP_HW_VALIDATION_ACTIVE (-109) +#define MP_HW_VALIDATION_ACTIVE ESP_MP_HW_VALIDATION_ACTIVE /* ******************************************************************************* ******************************************************************************* +** Global Settings: ** -** Primary Settings: +** Settings that start with "CONFIG_" are typically defined in sdkconfig.h ** -** WOLFSSL_ESP32_CRYPT_RSA_PRI -** Defined in wolfSSL settings.h: this turns on or off esp32_mp math library. -** Unless turned off, this is enabled by default for the ESP32 +** Primary Settings: ** ** NO_ESP32_CRYPT ** When defined, disables all hardware acceleration on the ESP32 ** ** NO_WOLFSSL_ESP32_CRYPT_HASH -** Used to disabled only hash hardware algorithms: SHA2, etc. +** Used to disabled only hash hardware, all algorithms: SHA2, etc. ** -** WOLFSSL_NOSHA512_224 -** Define to disable SHA-512/224 +** NO_WOLFSSL_ESP32_CRYPT_HASH_SHA +** When defined, disables only SHA hardware acceleration, uses SW. ** -** WOLFSSL_NOSHA512_256 -** Define to disable SHA-512/512 +** NO_WOLFSSL_ESP32_CRYPT_HASH_SHA224 +** When defined, disables only SHA-224 hardware acceleration, uses SW. ** -** NO_WOLFSSL_ESP32_CRYPT_AES -** Used to disable only AES hardware algorithms. Software used instead. +** NO_WOLFSSL_ESP32_CRYPT_HASH_SHA384 +** When defined, disables only SHA-384 hardware acceleration, uses SW. +** +** NO_WOLFSSL_ESP32_CRYPT_HASH_SHA256 +** When defined, disables only SHA-256 hardware acceleration, uses SW. +** +** NO_WOLFSSL_ESP32_CRYPT_HASH_SHA512 +** When defined, disables only SHA-512 hardware acceleration, uses SW. ** -** NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_MP_MUL -** Turns off hardware acceleration esp_mp_mul() +** WOLFSSL_NOSHA512_224 +** Define to disable SHA-512/224 ** -** NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_EXPTMOD -** Turns off hardware acceleration esp_mp_exptmod() +** WOLFSSL_NOSHA512_256 +** Define to disable SHA-512/512 ** -** NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_MULMOD -** Turns off hardware acceleration esp_mp_mulmod() +** WOLFSSL_ESP32_CRYPT_RSA_PRI +** Defined in wolfSSL settings.h: this turns on or off esp32_mp math library. +** Unless turned off, this is enabled by default for the ESP32 +** +** NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_MP_MUL +** Turns off hardware acceleration esp_mp_mul() +** +** NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_EXPTMOD +** Turns off hardware acceleration esp_mp_exptmod() +** +** NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_MULMOD +** Turns off hardware acceleration esp_mp_mulmod() +** +** NO_WOLFSSL_ESP32_CRYPT_AES +** Used to disable only AES hardware algorithms. Software used instead. ** ******************************************************************************* ** Math library settings: TFM @@ -99,14 +123,18 @@ ** WOLFSSL_ESP32_CRYPT_RSA_PRI_MP_MUL ** When defined, use hardware acceleration esp_mp_mul() ** for Large Number Multiplication: Z = X * Y +** Currently defined by default in tfm.c, see above to disable. ** ** WOLFSSL_ESP32_CRYPT_RSA_PRI_EXPTMOD ** When defined, use hardware acceleration esp_mp_exptmod() ** for Large Number Modular Exponentiation Z = X^Y mod M +** Currently defined by default in tfm.c, see above to disable. ** ** WOLFSSL_ESP32_CRYPT_RSA_PRI_MULMOD ** When defined, use hardware acceleration esp_mp_mulmod() ** for Large Number Modular Multiplication: Z = X * Y mod M +** Currently defined by default in tfm.c, see above to disable. +** ** ******************************************************************************* ** Optional Settings: @@ -119,6 +147,10 @@ ** Turns on development testing. Validates HW accelerated results to software ** - Automatically turns on WOLFSSL_HW_METRICS ** +** DEBUG_WOLFSSL_SHA_MUTEX +** Turns on diagnostic messages for SHA mutex. Note that given verbosity, +** there may be TLS timing issues encountered. Use with caution. +** ** LOG_LOCAL_LEVEL ** Debugging. Default value is ESP_LOG_DEBUG ** @@ -127,7 +159,10 @@ ** actually match the source data. ** ** WOLFSSL_ESP32_CRYPT_DEBUG -** When defined, enables hardware cryptography debugging +** When defined, enables hardware cryptography debugging. +** +** WOLFSSL_DEBUG_ESP_RSA_MULM_BITS +** Shows a warning when mulm falls back for minimum number of bits. ** ** NO_HW_MATH_TEST ** Even if HW is enabled, do not run HW math tests. See HW_MATH_ENABLED. @@ -142,7 +177,7 @@ ** matched with hardware. Useful only during development. Needs DEBUG_WOLFSSL ** ** ESP_PROHIBIT_SMALL_X -** When set to 1 X operands less than 8 bits will fall back to SW +** When set to 1 X operands less than 8 bits will fall back to SW. ** ** ESP_NO_ERRATA_MITIGATION ** Disable all errata mitigation code. @@ -150,23 +185,31 @@ ** USE_ESP_DPORT_ACCESS_READ_BUFFER ** Sets ESP_NO_ERRATA_MITIGATION and uses esp_dport_access_read_buffer() ** +** ESP_MONITOR_HW_TASK_LOCK +** Although wolfSSL is in general not fully thread safe, this option +** enables some features that can be useful in a multi-threaded environment. +** ******************************************************************************* ** Settings used from +** see .\esp-idf\v[N]\components\esp_common\include ******************************************************************************* ** ** ESP_IDF_VERSION_MAJOR -** +** Espressif ESP-IDF Version (e.g. 4, 5) ** ******************************************************************************* ** Settings used from ESP-IDF (sdkconfig.h) ******************************************************************************* ** +** CONFIG_IDF_TARGET_[SoC] +** CONFIG_IDF_TARGET_ESP32 +** CONFIG_IDF_TARGET_ESP32S2 +** CONFIG_IDF_TARGET_ESP32S3 +** CONFIG_IDF_TARGET_ESP32C3 +** CONFIG_IDF_TARGET_ESP32C6 ** -******************************************************************************* -** -** -******************************************************************************* -** Informative settings. Not meant to be edited +]******************************************************************************* +** Informative settings. Not meant to be edited: ******************************************************************************* ** ** HW_MATH_ENABLED @@ -181,23 +224,26 @@ #define LOG_LOCAL_LEVEL ESP_LOG_DEBUG #else #undef LOG_LOCAL_LEVEL - #define LOG_LOCAL_LEVEL ESP_LOG_DEBUG + #define LOG_LOCAL_LEVEL CONFIG_LOG_DEFAULT_LEVEL #endif #include #if defined(CONFIG_IDF_TARGET_ESP32) + /* there's no SHA-224 HW on the ESP32 */ + #undef NO_WOLFSSL_ESP32_CRYPT_HASH_SHA224 + #define NO_WOLFSSL_ESP32_CRYPT_HASH_SHA224 #include "soc/dport_reg.h" - #include "soc/hwcrypto_reg.h" + #include #if ESP_IDF_VERSION_MAJOR < 5 - #include "soc/cpu.h" + #include #endif #if defined(ESP_IDF_VERSION_MAJOR) && ESP_IDF_VERSION_MAJOR >= 5 - #include "esp_private/periph_ctrl.h" + #include #else - #include "driver/periph_ctrl.h" + #include #endif #if ESP_IDF_VERSION_MAJOR >= 4 @@ -205,52 +251,159 @@ #else #include #endif - #define ESP_PROHIBIT_SMALL_X 0 + #define ESP_PROHIBIT_SMALL_X FALSE + /***** END CONFIG_IDF_TARGET_ESP32 *****/ + +#elif defined(CONFIG_IDF_TARGET_ESP32C3) + #include + #include + + #if ESP_IDF_VERSION_MAJOR < 5 + #include + #endif + + #if defined(ESP_IDF_VERSION_MAJOR) && ESP_IDF_VERSION_MAJOR >= 5 + #include + #else + #include + #endif + + #if ESP_IDF_VERSION_MAJOR >= 4 + /* #include */ + #else + #include + #endif + +/* If for some reason there's a desire to disable specific HW on the C3: */ +/* #undef NO_WOLFSSL_ESP32_CRYPT_HASH_SHA */ +/* #define NO_WOLFSSL_ESP32_CRYPT_HASH_SHA there is SHA HW on C3 */ +/* #undef NO_WOLFSSL_ESP32_CRYPT_HASH_SHA224 */ +/* #define NO_WOLFSSL_ESP32_CRYPT_HASH_SHA224 there is SHA224 HW on C3 */ +/* #undef NO_WOLFSSL_ESP32_CRYPT_HASH_SHA256 */ +/* #define NO_WOLFSSL_ESP32_CRYPT_HASH_SHA256 there is SHA256 HW on C3 */ + + /* Code will fall back to SW with warning if these are removed: + * Note there is no SHA384/SHA512 HW on ESP32-C3 */ + #undef NO_WOLFSSL_ESP32_CRYPT_HASH_SHA384 + #define NO_WOLFSSL_ESP32_CRYPT_HASH_SHA384 + #undef NO_WOLFSSL_ESP32_CRYPT_HASH_SHA512 + #define NO_WOLFSSL_ESP32_CRYPT_HASH_SHA512 + /***** END CONFIG_IDF_TARGET_ESP32C3 *****/ + +#elif defined(CONFIG_IDF_TARGET_ESP32C6) + #include + #include + + #if ESP_IDF_VERSION_MAJOR < 5 + #include + #endif + + #if defined(ESP_IDF_VERSION_MAJOR) && ESP_IDF_VERSION_MAJOR >= 5 + #include + #else + #include + #endif + + #if ESP_IDF_VERSION_MAJOR >= 4 + /* #include */ + #else + #include + #endif + +/* If for some reason there's a desire to disable specific SHA HW on the C6: */ +/* #undef NO_WOLFSSL_ESP32_CRYPT_HASH_SHA */ +/* #define NO_WOLFSSL_ESP32_CRYPT_HASH_SHA there *is* SHA HW on C6 */ +/* #undef NO_WOLFSSL_ESP32_CRYPT_HASH_SHA224 */ +/* #define NO_WOLFSSL_ESP32_CRYPT_HASH_SHA224 there *is* SHA224 HW on C6 */ +/* #undef NO_WOLFSSL_ESP32_CRYPT_HASH_SHA256 */ +/* #define NO_WOLFSSL_ESP32_CRYPT_HASH_SHA256 there *is* SHA225 HW on C6 */ + + /* Code will fall back to SW with warning if these are removed: + * note there is no SHA384/SHA512 HW on C6 */ + #undef NO_WOLFSSL_ESP32_CRYPT_HASH_SHA384 + #define NO_WOLFSSL_ESP32_CRYPT_HASH_SHA384 + #undef NO_WOLFSSL_ESP32_CRYPT_HASH_SHA512 + #define NO_WOLFSSL_ESP32_CRYPT_HASH_SHA512 + /***** END CONFIG_IDF_TARGET_ESP32C6 *****/ + #elif defined(CONFIG_IDF_TARGET_ESP32S2) #include "soc/dport_reg.h" - #include "soc/hwcrypto_reg.h" + #include #if defined(ESP_IDF_VERSION_MAJOR) && ESP_IDF_VERSION_MAJOR >= 5 - #include "esp_private/periph_ctrl.h" + #include #else - #include "driver/periph_ctrl.h" + #include #endif #define ESP_PROHIBIT_SMALL_X 0 + /***** END CONFIG_IDF_TARGET_ESP32S2 *****/ + #elif defined(CONFIG_IDF_TARGET_ESP32S3) #include "soc/dport_reg.h" - #include "soc/hwcrypto_reg.h" + #include #if defined(ESP_IDF_VERSION_MAJOR) && ESP_IDF_VERSION_MAJOR >= 5 - #include "esp_private/periph_ctrl.h" + #include #else - #include "driver/periph_ctrl.h" + #include #endif #define ESP_PROHIBIT_SMALL_X 0 -#elif defined(CONFIG_IDF_TARGET_ESP32C3) - /* no includes for ESP32C3 at this time (no HW implemented yet) */ + #else /* not yet supported. no HW */ -#endif + #undef NO_WOLFSSL_ESP32_CRYPT_HASH_SHA + #define NO_WOLFSSL_ESP32_CRYPT_HASH_SHA + #undef NO_WOLFSSL_ESP32_CRYPT_HASH_SHA224 + #define NO_WOLFSSL_ESP32_CRYPT_HASH_SHA224 + #undef NO_WOLFSSL_ESP32_CRYPT_HASH_SHA256 + #define NO_WOLFSSL_ESP32_CRYPT_HASH_SHA256 + #undef NO_WOLFSSL_ESP32_CRYPT_HASH_SHA384 + #define NO_WOLFSSL_ESP32_CRYPT_HASH_SHA384 + #undef NO_WOLFSSL_ESP32_CRYPT_HASH_SHA512 + #define NO_WOLFSSL_ESP32_CRYPT_HASH_SHA512 + /***** END CONFIG_IDF_TARGET_[x] config unknown *****/ + +#endif /* CONFIG_IDF_TARGET target check */ + +#ifndef NO_WOLFSSL_ESP32_CRYPT_RSA_PRI + #if defined(NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_MP_MUL) && \ + defined(NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_MULMOD) && \ + defined(NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_EXPTMOD) + #warning "MP_MUL, MULMOD, EXPTMOD all turned off. " && \ + "Define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI to disable all math HW" + #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI + #endif +#endif /* !NO_WOLFSSL_ESP32_CRYPT_RSA_PRI */ #if defined(USE_ESP_DPORT_ACCESS_READ_BUFFER) #define ESP_NO_ERRATA_MITIGATION #endif +#ifdef SINGLE_THREADED + #undef ESP_MONITOR_HW_TASK_LOCK +#else + /* Unless explicitly disabled, monitor task lock when not single thread. */ + #ifndef ESP_DISABLE_HW_TASK_LOCK + #define ESP_MONITOR_HW_TASK_LOCK + #endif +#endif + #ifdef __cplusplus extern "C" { #endif - /* - ****************************************************************************** - ** Some common esp utilities - ****************************************************************************** - */ +/* +****************************************************************************** +** Some common esp utilities +****************************************************************************** +*/ WOLFSSL_LOCAL int esp_ShowExtendedSystemInfo(void); /* Compare MATH_INT_T A to MATH_INT_T B * During debug, the strings name_A and name_B can help * identify variable name. */ - WOLFSSL_LOCAL int esp_mp_cmp(char* name_A, MATH_INT_T* A, char* name_B, MATH_INT_T* B); + WOLFSSL_LOCAL int esp_mp_cmp(char* name_A, MATH_INT_T* A, + char* name_B, MATH_INT_T* B); /* Show MATH_INT_T value attributes. */ WOLFSSL_LOCAL int esp_show_mp_attributes(char* c, MATH_INT_T* X); @@ -263,24 +416,34 @@ extern "C" * identify variable name. */ WOLFSSL_LOCAL int esp_show_mp(char* name_X, MATH_INT_T* X); - /* To use a Mutex, if must first be initialized */ + /* To use a Mutex, it must first be initialized. */ WOLFSSL_LOCAL int esp_CryptHwMutexInit(wolfSSL_Mutex* mutex); - /* When the HW is in use, the mutex will be locked. */ - WOLFSSL_LOCAL int esp_CryptHwMutexLock(wolfSSL_Mutex* mutex, TickType_t block_time); + /* Take the mutex to indicate the HW is in use. Wait up to [block_time]. + * When the HW in use the mutex will be locked. */ + WOLFSSL_LOCAL int esp_CryptHwMutexLock(wolfSSL_Mutex* mutex, + TickType_t block_time); /* Release the mutex to indicate the HW is no longer in use. */ WOLFSSL_LOCAL int esp_CryptHwMutexUnLock(wolfSSL_Mutex* mutex); -#ifndef NO_AES + /* Validation active check. When active, we'll fall back to SW. */ + WOLFSSL_LOCAL int esp_hw_validation_active(void); + +/* +******************************************************************************* +** AES features: +******************************************************************************* +*/ +#ifndef NO_AES #if ESP_IDF_VERSION_MAJOR >= 4 #include "esp32/rom/aes.h" #else #include "rom/aes.h" #endif - typedef enum tagES32_AES_PROCESS + typedef enum tagES32_AES_PROCESS /* TODO what's this ? */ { ESP32_AES_LOCKHW = 1, ESP32_AES_UPDATEKEY_ENCRYPT = 2, @@ -289,36 +452,47 @@ extern "C" } ESP32_AESPROCESS; struct Aes; /* see aes.h */ +#if defined(WOLFSSL_HW_METRICS) + WOLFSSL_LOCAL int esp_hw_show_aes_metrics(void); + WOLFSSL_LOCAL int wc_esp32AesUnupportedLengthCountAdd(void); +#endif WOLFSSL_LOCAL int wc_esp32AesSupportedKeyLenValue(int keylen); WOLFSSL_LOCAL int wc_esp32AesSupportedKeyLen(struct Aes* aes); + WOLFSSL_LOCAL int wc_esp32AesCbcEncrypt(struct Aes* aes, - byte* out, - const byte* in, - word32 sz); + byte* out, + const byte* in, + word32 sz); WOLFSSL_LOCAL int wc_esp32AesCbcDecrypt(struct Aes* aes, - byte* out, - const byte* in, - word32 sz); - WOLFSSL_LOCAL int wc_esp32AesEncrypt(struct Aes *aes, const byte* in, byte* out); - WOLFSSL_LOCAL int wc_esp32AesDecrypt(struct Aes *aes, const byte* in, byte* out); - + byte* out, + const byte* in, + word32 sz); + WOLFSSL_LOCAL int wc_esp32AesEncrypt( struct Aes* aes, + const byte* in, + byte* out); + WOLFSSL_LOCAL int wc_esp32AesDecrypt( struct Aes* aes, + const byte* in, + byte* out); #endif /* ! NO_AES */ #ifdef WOLFSSL_ESP32_CRYPT_DEBUG void wc_esp32TimerStart(void); - uint64_t wc_esp32elapsedTime(void); + uint64_t wc_esp32elapsedTime(void); #endif /* WOLFSSL_ESP32_CRYPT_DEBUG */ +/* +******************************************************************************* +** Cryptographic hash algorithms (e.g. SHA[x]): +******************************************************************************* +*/ + #if !defined(NO_WOLFSSL_ESP32_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 #define SHA_CTX ETS_SHAContext #if ESP_IDF_VERSION_MAJOR >= 4 @@ -331,6 +505,9 @@ extern "C" #elif defined(CONFIG_IDF_TARGET_ESP32C3) #include "esp32c3/rom/sha.h" #define WC_ESP_SHA_TYPE SHA_TYPE + #elif defined(CONFIG_IDF_TARGET_ESP32C6) + #include "esp32c6/rom/sha.h" + #define WC_ESP_SHA_TYPE SHA_TYPE #elif defined(CONFIG_IDF_TARGET_ESP32H2) #include "esp32h2/rom/sha.h" #define WC_ESP_SHA_TYPE SHA_TYPE @@ -356,6 +533,7 @@ extern "C" ESP32_SHA_HW = 1, ESP32_SHA_SW = 2, ESP32_SHA_HW_COPY = 3, + ESP32_SHA_FREED = 4, ESP32_SHA_FAIL_NEED_UNROLL = -1 } ESP32_MODE; @@ -363,6 +541,9 @@ extern "C" { /* pointer to object the initialized HW; to track copies */ void* initializer; +#ifndef SINGLE_THREADED + void* task_owner; +#endif /* an ESP32_MODE value; typically: ** 0 init, @@ -388,37 +569,65 @@ extern "C" byte isfirstblock : 1; /* 1 bit only for true / false */ } WC_ESP32SHA; - WOLFSSL_LOCAL int esp_sha_init(WC_ESP32SHA* ctx, enum wc_HashType hash_type); + WOLFSSL_LOCAL int esp_sha_need_byte_reversal(WC_ESP32SHA* ctx); + WOLFSSL_LOCAL int esp_sha_init(WC_ESP32SHA* ctx, + enum wc_HashType hash_type); WOLFSSL_LOCAL int esp_sha_init_ctx(WC_ESP32SHA* ctx); WOLFSSL_LOCAL int esp_sha_try_hw_lock(WC_ESP32SHA* ctx); WOLFSSL_LOCAL int esp_sha_hw_unlock(WC_ESP32SHA* ctx); + /* esp_sha_hw_islocked: returns 0 if not locked, otherwise owner address */ + WOLFSSL_LOCAL int esp_sha_hw_islocked(WC_ESP32SHA* ctx); + WOLFSSL_LOCAL int esp_sha_call_count(); + WOLFSSL_LOCAL int esp_sha_lock_count(); + WOLFSSL_LOCAL int esp_sha_release_unfinished_lock(WC_ESP32SHA* ctx); + WOLFSSL_LOCAL int esp_sha_set_stray(WC_ESP32SHA* ctx); + struct wc_Sha; WOLFSSL_LOCAL int esp_sha_ctx_copy(struct wc_Sha* src, struct wc_Sha* dst); - WOLFSSL_LOCAL int esp_sha_digest_process(struct wc_Sha* sha, byte blockprocess); + WOLFSSL_LOCAL int esp_sha_digest_process(struct wc_Sha* sha, + byte blockprocess); WOLFSSL_LOCAL int esp_sha_process(struct wc_Sha* sha, const byte* data); - #ifndef NO_SHA256 +#ifdef DEBUG_WOLFSSL_SHA_MUTEX + /* testing HW release in task that did not lock */ + extern WC_ESP32SHA* stray_ctx; +#endif + +#ifndef NO_SHA256 struct wc_Sha256; - WOLFSSL_LOCAL int esp_sha224_ctx_copy(struct wc_Sha256* src, struct wc_Sha256* dst); - WOLFSSL_LOCAL int esp_sha256_ctx_copy(struct wc_Sha256* src, struct wc_Sha256* dst); - WOLFSSL_LOCAL int esp_sha256_digest_process(struct wc_Sha256* sha, byte blockprocess); - WOLFSSL_LOCAL int esp_sha256_process(struct wc_Sha256* sha, const byte* data); - WOLFSSL_LOCAL int esp32_Transform_Sha256_demo(struct wc_Sha256* sha256, const byte* data); + WOLFSSL_LOCAL int esp_sha224_ctx_copy(struct wc_Sha256* src, + struct wc_Sha256* dst); + WOLFSSL_LOCAL int esp_sha256_ctx_copy(struct wc_Sha256* src, + struct wc_Sha256* dst); + WOLFSSL_LOCAL int esp_sha256_digest_process(struct wc_Sha256* sha, + byte blockprocess); + WOLFSSL_LOCAL int esp_sha256_process(struct wc_Sha256* sha, + const byte* data); + WOLFSSL_LOCAL 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; - WOLFSSL_LOCAL int esp_sha384_ctx_copy(struct wc_Sha512* src, struct wc_Sha512* dst); - WOLFSSL_LOCAL int esp_sha512_ctx_copy(struct wc_Sha512* src, struct wc_Sha512* dst); + WOLFSSL_LOCAL int esp_sha384_ctx_copy(struct wc_Sha512* src, + struct wc_Sha512* dst); + WOLFSSL_LOCAL int esp_sha512_ctx_copy(struct wc_Sha512* src, + struct wc_Sha512* dst); WOLFSSL_LOCAL int esp_sha512_process(struct wc_Sha512* sha); - WOLFSSL_LOCAL int esp_sha512_digest_process(struct wc_Sha512* sha, byte blockproc); + WOLFSSL_LOCAL int esp_sha512_digest_process(struct wc_Sha512* sha, + byte blockproc); #endif #endif /* NO_SHA && etc */ +/* +******************************************************************************* +** RSA Big Math +******************************************************************************* +*/ + #if !defined(NO_RSA) || defined(HAVE_ECC) #if !defined(ESP_RSA_TIMEOUT_CNT) @@ -440,13 +649,14 @@ extern "C" MATH_INT_T* Y, /* X */ MATH_INT_T* M, /* P */ MATH_INT_T* Z); /* Y */ + /* HW_MATH_ENABLED is typically used in wolfcrypt tests */ #undef HW_MATH_ENABLED #define HW_MATH_ENABLED - #endif /* ! NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_EXPTMOD */ +#endif /* ! NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_EXPTMOD */ - #ifndef NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_MP_MUL - /* Z = X * Y */ +#ifndef NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_MP_MUL + /* Z = X * Y */ WOLFSSL_LOCAL int esp_mp_mul(MATH_INT_T* X, MATH_INT_T* Y, MATH_INT_T* Z); @@ -469,13 +679,25 @@ extern "C" #endif /* !NO_RSA || HAVE_ECC*/ - WOLFSSL_LOCAL int esp_hw_validation_active(void); - +/* Optionally enable some metrics to count interesting usage */ +/* +******************************************************************************* +** Usage metrics +******************************************************************************* +*/ #ifdef WOLFSSL_HW_METRICS - int esp_hw_show_mp_metrics(void); -#endif + /* Allow sha256 code to keep track of SW fallback during active HW */ + WOLFSSL_LOCAL int esp_sw_sha256_count_add(); -#define ESP_MP_HW_LOCK_MAX_DELAY ( TickType_t ) 0xffUL + /* show MP HW Metrics*/ + WOLFSSL_LOCAL int esp_hw_show_mp_metrics(void); + + /* show SHA HW Metrics*/ + WOLFSSL_LOCAL int esp_hw_show_sha_metrics(void); + + /* show all HW Metrics*/ + WOLFSSL_LOCAL int esp_hw_show_metrics(void); +#endif /* * Errata Mitigation. See @@ -483,6 +705,8 @@ extern "C" * https://www.espressif.com/sites/default/files/documentation/esp32-c3_errata_en.pdf * https://www.espressif.com/sites/default/files/documentation/esp32-s3_errata_en.pdf */ +#define ESP_MP_HW_LOCK_MAX_DELAY ( TickType_t ) 0xffUL + #if defined(CONFIG_IDF_TARGET_ESP32) && !defined(ESP_NO_ERRATA_MITIGATION) /* some of these may be tuned for specific silicon versions */ #define ESP_EM__MP_HW_WAIT_CLEAN {__asm__ __volatile__("memw");} @@ -517,6 +741,7 @@ extern "C" __asm__ __volatile__("nop"); /* 5 */ \ __asm__ __volatile__("nop"); /* 6 */ \ __asm__ __volatile__("nop"); /* 7 */ \ + __asm__ __volatile__("nop"); /* 8 */ \ }; #elif defined(CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240) #define ESP_EM__3_16 { \ @@ -555,4 +780,6 @@ extern "C" } #endif +#endif /* WOLFSSL_ESPIDF */ + #endif /* __ESP32_CRYPT_H__ */ diff --git a/wolfssl/wolfcrypt/settings.h b/wolfssl/wolfcrypt/settings.h index 477be211a3..0f05153bd7 100644 --- a/wolfssl/wolfcrypt/settings.h +++ b/wolfssl/wolfcrypt/settings.h @@ -394,15 +394,54 @@ #endif #if defined(WOLFSSL_ESP32) || defined(WOLFSSL_ESPWROOM32SE) - #ifndef NO_ESP32_CRYPT + #ifndef NO_ESP32_CRYPT #define WOLFSSL_ESP32_CRYPT #if defined(ESP32_USE_RSA_PRIMITIVE) && \ !defined(NO_WOLFSSL_ESP32_CRYPT_RSA_PRI) #define WOLFSSL_ESP32_CRYPT_RSA_PRI #define WOLFSSL_SMALL_STACK #endif - #endif -#endif + #endif + + #if defined(WOLFSSL_SP_RISCV32) + #if defined(CONFIG_IDF_TARGET_ESP32C2) \ + || defined(CONFIG_IDF_TARGET_ESP32C3) \ + || defined(CONFIG_IDF_TARGET_ESP32C6) + /* ok, only the known C2, C3, C6 chips allowed */ + #else + #error "WOLFSSL_SP_RISCV32 can only be used on RISC-V architecture" + #endif + #endif + #if defined(WOLFSSL_SM2) || defined(WOLFSSL_SM3) || defined(WOLFSSL_SM4) + /* SM settings */ + #undef WOLFSSL_BASE16 + #define WOLFSSL_BASE16 /* required for WOLFSSL_SM2 */ + + #undef WOLFSSL_SM4_ECB + #define WOLFSSL_SM4_ECB + + #undef WOLFSSL_SM4_CBC + #define WOLFSSL_SM4_CBC + + #undef WOLFSSL_SM4_CTR + #define WOLFSSL_SM4_CTR + + #undef WOLFSSL_SM4_GCM + #define WOLFSSL_SM4_GCM + + #undef WOLFSSL_SM4_CCM + #define WOLFSSL_SM4_CCM + + #undef HAVE_POLY1305 + #define HAVE_POLY1305 + + #undef HAVE_CHACHA + #define HAVE_CHACHA + + #undef HAVE_AESGCM + #define HAVE_AESGCM + #endif /* SM */ +#endif /* defined(WOLFSSL_ESP32) || defined(WOLFSSL_ESPWROOM32SE) */ #endif /* WOLFSSL_ESPIDF */ #if defined(WOLFSSL_RENESAS_TSIP) diff --git a/wolfssl/wolfcrypt/sha256.h b/wolfssl/wolfcrypt/sha256.h index 9dfd5e1d24..454290c42b 100644 --- a/wolfssl/wolfcrypt/sha256.h +++ b/wolfssl/wolfcrypt/sha256.h @@ -201,7 +201,9 @@ struct wc_Sha256 { word32 len; #endif #if defined(WOLFSSL_ESP32_CRYPT) && \ - !defined(NO_WOLFSSL_ESP32_CRYPT_HASH) + !defined(NO_WOLFSSL_ESP32_CRYPT_HASH) && \ + (!defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA256) || \ + !defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA224)) WC_ESP32SHA ctx; #endif #ifdef WOLFSSL_MAXQ10XX_CRYPTO diff --git a/wolfssl/wolfcrypt/sha512.h b/wolfssl/wolfcrypt/sha512.h index 33d34ee258..1c943d94ce 100644 --- a/wolfssl/wolfcrypt/sha512.h +++ b/wolfssl/wolfcrypt/sha512.h @@ -154,7 +154,8 @@ struct wc_Sha512 { word64* W; #endif #if defined(WOLFSSL_ESP32_CRYPT) && \ - !defined(NO_WOLFSSL_ESP32_CRYPT_HASH) + !defined(NO_WOLFSSL_ESP32_CRYPT_HASH) && \ + !defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA512) WC_ESP32SHA ctx; #endif #if defined(WOLFSSL_SILABS_SE_ACCEL) diff --git a/wolfssl/wolfcrypt/tfm.h b/wolfssl/wolfcrypt/tfm.h index 4c497266a0..7e850d3cbb 100644 --- a/wolfssl/wolfcrypt/tfm.h +++ b/wolfssl/wolfcrypt/tfm.h @@ -290,6 +290,8 @@ #define FP_MASK (fp_digit)(-1) #define FP_DIGIT_MAX FP_MASK #define FP_SIZE (FP_MAX_SIZE/DIGIT_BIT) +#define MP_SIZE (FP_MAX_SIZE/DIGIT_BIT) /* for compatibility with SP_INT */ + #define FP_MAX_PRIME_SIZE (FP_MAX_BITS/(2*CHAR_BIT)) /* In terms of FP_MAX_BITS, it is double the size possible for a number