diff --git a/IDE/Espressif/ESP-IDF/libs/CMakeLists.txt b/IDE/Espressif/ESP-IDF/libs/CMakeLists.txt
index b8498e08f..b690fb9fb 100644
--- a/IDE/Espressif/ESP-IDF/libs/CMakeLists.txt
+++ b/IDE/Espressif/ESP-IDF/libs/CMakeLists.txt
@@ -1,6 +1,24 @@
#
+# Copyright (C) 2014-2022 wolfSSL Inc.
+#
+# This file is part of wolfSSH.
+#
+# wolfSSH is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# wolfSSH is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with wolfSSH. If not, see .
+#
+#
# cmake for wolfssl
-#
+#
cmake_minimum_required(VERSION 3.5)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DWOLFSSL_USER_SETTINGS")
@@ -12,15 +30,24 @@ set(COMPONENT_SRCDIRS "./src/"
"./wolfcrypt/src/"
"./wolfcrypt/src/port/Espressif/"
"./wolfcrypt/src/port/atmel/"
+# "$ENV{IDF_PATH}/components/soc/esp32s3/include/soc"
)
set(COMPONENT_REQUIRES lwip)
+
+# RTOS_IDF_PATH is typically:
+# "/Users/{username}/Desktop/esp-idf/components/freertos/include/freertos"
+# depending on the environment, we may need to swap backslashes with forward slashes
+string(REPLACE "\\" "/" RTOS_IDF_PATH "$ENV{IDF_PATH}/components/freertos/include/freertos")
+# ESP-IDF after version 4.4x has a different RTOS directory structure
+string(REPLACE "\\" "/" RTOS_IDF_PATH5 "$ENV{IDF_PATH}/components/freertos/FreeRTOS-Kernel/include/freertos")
+
if(IS_DIRECTORY ${IDF_PATH}/components/freertos/FreeRTOS-Kernel/)
set(COMPONENT_ADD_INCLUDEDIRS
"."
"./include"
- "../freertos/FreeRTOS-Kernel/include/freertos"
+ "${RTOS_IDF_PATH5}"
"${WOLFSSL_ROOT}"
)
else()
@@ -28,7 +55,7 @@ else()
set(COMPONENT_ADD_INCLUDEDIRS
"."
"./include"
- "../freertos/include/freertos"
+ "${RTOS_IDF_PATH}"
"${WOLFSSL_ROOT}"
)
endif()
@@ -49,3 +76,11 @@ set(COMPONENT_SRCEXCLUDE
)
register_component()
+
+# check to see if there's both a local copy and EDP-IDF copy of the wolfssl components
+if( EXISTS "${CMAKE_HOME_DIRECTORY}/components/wolfssl/" AND EXISTS "$ENV{IDF_PATH}/components/wolfssl/" )
+ message(STATUS "")
+ message(STATUS "WARNING: Found components/wolfssl in both local project and IDF_PATH")
+ message(STATUS "")
+endif()
+# end multiple component check
diff --git a/IDE/Espressif/ESP-IDF/libs/component.mk b/IDE/Espressif/ESP-IDF/libs/component.mk
index 2efebab9b..78b72380d 100644
--- a/IDE/Espressif/ESP-IDF/libs/component.mk
+++ b/IDE/Espressif/ESP-IDF/libs/component.mk
@@ -1,17 +1,37 @@
-#
-# Component Makefile
-#
-
-COMPONENT_ADD_INCLUDEDIRS := . ./include
-COMPONENT_ADD_INCLUDEDIRS += ../freertos/include/freertos/
-
-COMPONENT_SRCDIRS := src wolfcrypt/src
-COMPONENT_SRCDIRS += wolfcrypt/src/port/Espressif
-COMPONENT_SRCDIRS += wolfcrypt/src/port/atmel
-
-CFLAGS +=-DWOLFSSL_USER_SETTINGS
-
-COMPONENT_OBJEXCLUDE := wolfcrypt/src/aes_asm.o
-COMPONENT_OBJEXCLUDE += wolfcrypt/src/evp.o
-COMPONENT_OBJEXCLUDE += wolfcrypt/src/misc.o
-COMPONENT_OBJEXCLUDE += src/bio.o
+#
+# Copyright (C) 2014-2022 wolfSSL Inc.
+#
+# This file is part of wolfSSH.
+#
+# wolfSSH is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# wolfSSH is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with wolfSSH. If not, see .
+#
+#
+# Component Makefile
+#
+
+COMPONENT_ADD_INCLUDEDIRS := . ./include
+
+COMPONENT_ADD_INCLUDEDIRS += "$ENV{IDF_PATH}/components/freertos/include/freertos"
+# COMPONENT_ADD_INCLUDEDIRS += "$ENV{IDF_PATH}/soc/esp32s3/include/soc"
+
+COMPONENT_SRCDIRS := src wolfcrypt/src
+COMPONENT_SRCDIRS += wolfcrypt/src/port/Espressif
+COMPONENT_SRCDIRS += wolfcrypt/src/port/atmel
+
+CFLAGS +=-DWOLFSSL_USER_SETTINGS
+
+COMPONENT_OBJEXCLUDE := wolfcrypt/src/aes_asm.o
+COMPONENT_OBJEXCLUDE += wolfcrypt/src/evp.o
+COMPONENT_OBJEXCLUDE += wolfcrypt/src/misc.o
+COMPONENT_OBJEXCLUDE += src/bio.o
diff --git a/IDE/Espressif/ESP-IDF/user_settings.h b/IDE/Espressif/ESP-IDF/user_settings.h
index 23386646d..7c512dc46 100644
--- a/IDE/Espressif/ESP-IDF/user_settings.h
+++ b/IDE/Espressif/ESP-IDF/user_settings.h
@@ -1,6 +1,6 @@
/* user_settings.h
*
- * Copyright (C) 2006-2021 wolfSSL Inc.
+ * Copyright (C) 2006-2022 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
@@ -19,22 +19,24 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#undef WOLFSSL_ESPIDF
+#undef WOLFSSL_ESPWROOM32
+#undef WOLFSSL_ESPWROOM32SE
+#undef WOLFSSL_ESPWROOM32
+#undef WOLFSSL_ESP8266
+
#define WOLFSSL_ESPIDF
/*
* choose ONE of these Espressif chips to define:
- *
+ *
* WOLFSSL_ESPWROOM32
* WOLFSSL_ESPWROOM32SE
* WOLFSSL_ESP8266
- *
- * comment out the others:
*/
#define WOLFSSL_ESPWROOM32
-/* #define WOLFSSL_ESPWROOM32SE */
-/* #define WOLFSSL_ESP8266 */
+/* #define DEBUG_WOLFSSL_VERBOSE */
#define BENCH_EMBEDDED
#define USE_CERT_BUFFERS_2048
@@ -88,7 +90,7 @@
/* Define USE_FAST_MATH and SMALL_STACK */
#define ESP32_USE_RSA_PRIMITIVE
/* threshold for performance adjustment for hw primitive use */
- /* X bits of G^X mod P greater than */
+ /* X bits of G^X mod P greater than */
#define EPS_RSA_EXPT_XBTIS 36
/* X and Y of X * Y mod P greater than */
#define ESP_RSA_MULM_BITS 2000
diff --git a/wolfcrypt/src/port/Espressif/esp32_aes.c b/wolfcrypt/src/port/Espressif/esp32_aes.c
index cce7a3016..0256685cb 100644
--- a/wolfcrypt/src/port/Espressif/esp32_aes.c
+++ b/wolfcrypt/src/port/Espressif/esp32_aes.c
@@ -1,6 +1,6 @@
/* esp32_aes.c
*
- * Copyright (C) 2006-2021 wolfSSL Inc.
+ * Copyright (C) 2006-2022 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
@@ -19,6 +19,10 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
+/*
+ * WOLFSSL_SUCCESS and WOLFSSL_FAILURE values should only
+ * be used in the ssl layer, not in wolfCrypt
+ **/
#include
#include
@@ -36,13 +40,18 @@
#include "wolfssl/wolfcrypt/port/Espressif/esp32-crypt.h"
static const char* TAG = "wolf_hw_aes";
+
/* mutex */
static wolfSSL_Mutex aes_mutex;
+
+/* keep track as to whether esp aes is initialized */
static int espaes_CryptHwMutexInit = 0;
/*
* 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()
{
@@ -50,21 +59,29 @@ static int esp_aes_hw_InUse()
ESP_LOGV(TAG, "enter esp_aes_hw_InUse");
- if(espaes_CryptHwMutexInit == 0) {
+ if (espaes_CryptHwMutexInit == 0) {
ret = esp_CryptHwMutexInit(&aes_mutex);
- if(ret == 0){
+ if (ret == 0) {
+ /* flag esp aes as initialized */
espaes_CryptHwMutexInit = 1;
- } else {
- ESP_LOGE(TAG, "aes mutx initialization failed.");
+ }
+ else {
+ ESP_LOGE(TAG, "aes mutex initialization failed.");
return -1;
}
}
+ else {
+ /* esp aes has already been initialized */
+ }
+
/* lock hardware */
ret = esp_CryptHwMutexLock(&aes_mutex, portMAX_DELAY);
+
if(ret != 0) {
ESP_LOGE(TAG, "aes engine lock failed.");
return -1;
}
+
/* Enable AES hardware */
periph_module_enable(PERIPH_AES_MODULE);
@@ -92,23 +109,27 @@ static void esp_aes_hw_Leave( void )
*/
static void esp_aes_hw_Set_KeyMode(Aes *ctx, ESP32_AESPROCESS mode)
{
- int i;
+ word32 i;
word32 mode_ = 0;
- ESP_LOGV(TAG, "enter esp_aes_hw_Set_KeyMode");
+ ESP_LOGV(TAG, " enter esp_aes_hw_Set_KeyMode");
/* check mode */
if(mode == ESP32_AES_UPDATEKEY_ENCRYPT) {
mode_ = 0;
- } else if(mode == ESP32_AES_UPDATEKEY_DECRYPT){
- mode_ = 4;
- } else {
- ESP_LOGE(TAG, "unexpected error.");
- return;
+ }
+ else {
+ if (mode == ESP32_AES_UPDATEKEY_DECRYPT) {
+ mode_ = 4;
+ }
+ else {
+ ESP_LOGE(TAG, " >> unexpected error.");
+ return;
+ }
}
/* update key */
- for(i=0;i<(ctx->keylen)/sizeof(word32);i++){
+ for(i=0; i<(ctx->keylen)/sizeof(word32); i++){
DPORT_REG_WRITE(AES_KEY_BASE + (i*4), *(((word32*)ctx->key) + i));
}
@@ -127,7 +148,7 @@ static void esp_aes_hw_Set_KeyMode(Aes *ctx, ESP32_AESPROCESS mode)
}
DPORT_REG_WRITE(AES_MODE_REG, mode_);
- ESP_LOGV(TAG, "leave esp_aes_hw_Setkey");
+ ESP_LOGV(TAG, " leave esp_aes_hw_Setkey");
}
/*
@@ -181,6 +202,7 @@ int wc_esp32AesEncrypt(Aes *aes, const byte* in, byte* out)
esp_aes_hw_Leave();
return 0;
}
+
/*
* wc_esp32AesDecrypt
* @brief: a one block decrypt of the input block, into the output block
@@ -202,6 +224,7 @@ int wc_esp32AesDecrypt(Aes *aes, const byte* in, byte* out)
esp_aes_hw_Leave();
return 0;
}
+
/*
* wc_esp32AesCbcEncrypt
* @brief: Encrypts a plain text message from the input buffer, and places the
@@ -281,8 +304,9 @@ int wc_esp32AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz)
esp_aes_bk((in + offset), (out + offset));
/* XOR block with IV for CBC */
- for (i = 0; i < AES_BLOCK_SIZE; i++)
+ for (i = 0; i < AES_BLOCK_SIZE; i++) {
(out + offset)[i] ^= iv[i];
+ }
/* store IV for next block */
XMEMCPY(iv, temp_block, AES_BLOCK_SIZE);
diff --git a/wolfcrypt/src/port/Espressif/esp32_mp.c b/wolfcrypt/src/port/Espressif/esp32_mp.c
index af0192989..a7eb1fdd7 100644
--- a/wolfcrypt/src/port/Espressif/esp32_mp.c
+++ b/wolfcrypt/src/port/Espressif/esp32_mp.c
@@ -1,6 +1,6 @@
/* esp32_mp.c
*
- * Copyright (C) 2006-2021 wolfSSL Inc.
+ * Copyright (C) 2006-2022 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
@@ -58,46 +58,91 @@ static wolfSSL_Mutex mp_mutex;
static int espmp_CryptHwMutexInit = 0;
/*
* check if the hw is ready before accessing it
+*
+* When the RSA Accelerator is released from reset, the register RSA_CLEAN_REG
+* reads 0 and an initialization process begins. Hardware initializes the four
+* memory blocks by setting them to 0. After initialization is complete,
+* RSA_CLEAN_REG reads 1. For this reason, software should query RSA_CLEAN_REG
+* after being released from reset, and before writing to any RSA Accelerator
+* memory blocks or registers for the first time.
*/
static int esp_mp_hw_wait_clean()
{
word32 timeout = 0;
- while(!ESP_TIMEOUT(++timeout) &&
- DPORT_REG_READ(RSA_CLEAN_REG) != 1) { }
- if(ESP_TIMEOUT(timeout)) {
+ while(!ESP_TIMEOUT(++timeout) &&
+ DPORT_REG_READ(RSA_CLEAN_REG) != 1) {
+ /* wait. expected delay 1 to 2 uS */
+ }
+
+ if (ESP_TIMEOUT(timeout)) {
ESP_LOGE(TAG, "waiting hw ready is timed out.");
return MP_NG;
}
- return MP_OKAY;
+ return MP_OKAY;
}
+
/*
* lock hw engine.
* this should be called before using engine.
+*
+* returns 0 if the hw lock was initialized and mutex lock
+*
+* See Chapter 24:
+* https://www.espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf
+*
+* The RSA Accelerator is activated by enabling the corresponding peripheral
+* clock, and by clearing the DPORT_RSA_PD bit in the DPORT_RSA_PD_CTRL_REG
+* register. This releases the RSA Accelerator from reset.
+*
+* 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,
+* RSA_CLEAN_REG reads 1. For this reason, software should query RSA_CLEAN_REG
+* 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()
{
int ret = 0;
- if(espmp_CryptHwMutexInit == 0) {
+ ESP_LOGV(TAG, "enter esp_mp_hw_lock");
+
+ if (espmp_CryptHwMutexInit == 0) {
ret = esp_CryptHwMutexInit(&mp_mutex);
- if(ret == 0){
+ if (ret == 0) {
+ /* flag esp mp as initialized */
espmp_CryptHwMutexInit = 1;
- } else {
+ }
+ else {
ESP_LOGE(TAG, "mp mutx initialization failed.");
return MP_NG;
}
}
+ else {
+ /* esp aes has already been iniitlized */
+ }
+
/* lock hardware */
ret = esp_CryptHwMutexLock(&mp_mutex, portMAX_DELAY);
- if(ret != 0) {
+
+ if (ret != 0) {
ESP_LOGE(TAG, "mp engine lock failed.");
return MP_NG;
}
+
/* Enable RSA hardware */
periph_module_enable(PERIPH_RSA_MODULE);
+ /* clear bit to enable hardware operation; (set to disable)
+ */
DPORT_REG_CLR_BIT(DPORT_RSA_PD_CTRL_REG, DPORT_RSA_PD);
+
+ /* remionder: wait until RSA_CLEAN_REG reads 1
+ * see esp_mp_hw_wait_clean()
+ */
+
+ ESP_LOGV(TAG, "leave esp_mp_hw_lock");
return ret;
}
/*
@@ -105,12 +150,17 @@ static int esp_mp_hw_lock()
*/
static void esp_mp_hw_unlock( void )
{
+ /* set bit to disabled hardware operation; (clear to enable)
+ */
+ DPORT_REG_SET_BIT(DPORT_RSA_PD_CTRL_REG, DPORT_RSA_PD);
+
/* Disable RSA hardware */
periph_module_disable(PERIPH_RSA_MODULE);
/* unlock */
esp_CryptHwMutexUnLock(&mp_mutex);
}
+
/* this is based on an article by Cetin Kaya Koc, A New Algorithm for Inversion*/
/* mod p^k, June 28 2017. */
static int esp_calc_Mdash(mp_int *M, word32 k, mp_digit* md)
@@ -126,9 +176,9 @@ static int esp_calc_Mdash(mp_int *M, word32 k, mp_digit* md)
bi = b0;
x = 0;
- for(i = 0; i < k; i++) {
+ for (i = 0; i < k; i++) {
xi = bi % 2;
- if(xi < 0){
+ if (xi < 0) {
xi *= -1;
}
bi = (bi - N * xi) / 2;
@@ -138,6 +188,7 @@ static int esp_calc_Mdash(mp_int *M, word32 k, mp_digit* md)
*md = ~x + 1;
return MP_OKAY;
}
+
/* start hw process */
static void process_start(word32 reg)
{
@@ -146,87 +197,100 @@ static void process_start(word32 reg)
/* start process */
DPORT_REG_WRITE(reg, 1);
}
+
/* wait until done */
static int wait_uitil_done(word32 reg)
{
word32 timeout = 0;
/* wait until done && not timeout */
- while(!ESP_TIMEOUT(++timeout) &&
- DPORT_REG_READ(reg) != 1) { }
+ while (!ESP_TIMEOUT(++timeout) &&
+ DPORT_REG_READ(reg) != 1) {
+ /* wait */
+ }
/* clear interrupt */
DPORT_REG_WRITE(RSA_INTERRUPT_REG, 1);
- if(ESP_TIMEOUT(timeout)) {
+ if (ESP_TIMEOUT(timeout)) {
ESP_LOGE(TAG, "rsa operation is timed out.");
return MP_NG;
}
return MP_OKAY;
}
+
/* read data from memory into mp_init */
-static void esp_memblock_to_mpint(word32 mem_address, mp_int* mp, word32 numwords)
+static void esp_memblock_to_mpint(word32 mem_address,
+ mp_int* mp,
+ word32 numwords)
{
esp_dport_access_read_buffer((uint32_t*)mp->dp, mem_address, numwords);
mp->used = numwords;
}
-/* write mp_init into memory block */
+/* write mp_init into memory block
+ */
static void esp_mpint_to_memblock(word32 mem_address, const mp_int* mp,
const word32 bits,
const word32 hwords)
{
+ /* init */
word32 i;
word32 len = (bits / 8 + ((bits & 7) != 0 ? 1 : 0));
- len = (len+sizeof(word32)-1)/sizeof(word32);
+ len = (len + sizeof(word32)-1) / sizeof(word32);
- for(i=0;i < hwords; i++) {
- if(i < len) {
+ for (i=0; i < hwords; i++) {
+ if (i < len) {
DPORT_REG_WRITE(mem_address + (i * sizeof(word32)), mp->dp[i]);
- } else {
+ }
+ else {
DPORT_REG_WRITE(mem_address + (i * sizeof(word32)), 0);
}
}
}
-/* return needed hw words. */
-/* supported words length */
-/* words : {16 , 32, 48, 64, 80, 96, 112, 128} */
-/* bits : {512,1024, 1536, 2048, 2560, 3072, 3584, 4096} */
+/* return needed hw words.
+ * supported words length
+ * words : {16 , 32, 48, 64, 80, 96, 112, 128}
+ * bits : {512,1024, 1536, 2048, 2560, 3072, 3584, 4096}
+ */
static word32 words2hwords(word32 wd)
{
- const word32 shit_ = 4;
+ const word32 bit_shift = 4;
- return (((wd + 0xf)>>shit_)<> bit_shift) << bit_shift);
}
+
/* count the number of words is needed for bits */
static word32 bits2words(word32 bits)
{
/* 32 bits */
const word32 d = sizeof(word32) * WOLFSSL_BIT_SIZE;
- return((bits + (d - 1))/d);
+ return ((bits + (d - 1)) / d);
}
+
/* get rinv */
static int esp_get_rinv(mp_int *rinv, mp_int *M, word32 exp)
{
int ret = 0;
/* 2^(exp)*/
- if((ret = mp_2expt(rinv, exp)) != MP_OKAY) {
+ if ((ret = mp_2expt(rinv, exp)) != MP_OKAY) {
ESP_LOGE(TAG, "failed to calculate mp_2expt()");
return ret;
}
/* r_inv = R^2 mod M(=P) */
- if(ret == 0 && (ret = mp_mod(rinv, M, rinv)) != MP_OKAY){
+ if (ret == 0 && (ret = mp_mod(rinv, M, rinv)) != MP_OKAY) {
ESP_LOGE(TAG, "failed to calculate mp_mod()");
return ret;
}
return ret;
}
-/* Z = X * Y; */
+
+/* Z = X * Y; */
int esp_mp_mul(fp_int* X, fp_int* Y, fp_int* Z)
{
int ret = 0;
@@ -268,34 +332,46 @@ int esp_mp_mul(fp_int* X, fp_int* Y, fp_int* Z)
* 9. Release the hw engine
*/
/* lock hw for use */
- if((ret = esp_mp_hw_lock()) != MP_OKAY)
+ if ((ret = esp_mp_hw_lock()) != MP_OKAY) {
return ret;
+ }
- if((ret = esp_mp_hw_wait_clean()) != MP_OKAY){
+ if((ret = esp_mp_hw_wait_clean()) != MP_OKAY) {
return ret;
}
/* step.1 (2*N/512) => N/256. 512 bits => 16 words */
DPORT_REG_WRITE(RSA_MULT_MODE_REG, (hwWords_sz >> 3) - 1 + 8);
/* step.2 write X, M and r_inv into memory */
- esp_mpint_to_memblock(RSA_MEM_X_BLOCK_BASE, X, Xs, hwWords_sz);
+ esp_mpint_to_memblock(RSA_MEM_X_BLOCK_BASE,
+ X,
+ Xs,
+ hwWords_sz);
/* Y(let-extend) */
- esp_mpint_to_memblock(RSA_MEM_Z_BLOCK_BASE + (hwWords_sz<<2), Y, Ys, hwWords_sz);
+ esp_mpint_to_memblock(RSA_MEM_Z_BLOCK_BASE + (hwWords_sz<<2),
+ Y,
+ Ys,
+ hwWords_sz);
/* step.3 start process */
process_start(RSA_MULT_START_REG);
/* step.4,5 wait until done */
- wait_uitil_done(RSA_INTERRUPT_REG);
+ ret = wait_uitil_done(RSA_INTERRUPT_REG);
+ if (ret != MP_OKAY) {
+ ESP_LOGE(TAG, "wait_uitil_done failed.");
+ return ret;
+ }
/* step.6 read the result form MEM_Z */
esp_memblock_to_mpint(RSA_MEM_Z_BLOCK_BASE, Z, BITS_TO_WORDS(Zs));
/* step.7 clear and release hw */
esp_mp_hw_unlock();
- Z->sign = (Z->used > 0)? neg : MP_ZPOS;
+ Z->sign = (Z->used > 0) ? neg : MP_ZPOS;
return ret;
}
+
/* Z = X * Y (mod M) */
int esp_mp_mulmod(fp_int* X, fp_int* Y, fp_int* M, fp_int* Z)
{
@@ -313,7 +389,7 @@ int esp_mp_mulmod(fp_int* X, fp_int* Y, fp_int* M, fp_int* Z)
mp_digit mp;
/* neg check */
- if(X->sign != Y->sign) {
+ if (X->sign != Y->sign) {
/* X*Y becomes negative */
negcheck = 1;
}
@@ -327,7 +403,7 @@ int esp_mp_mulmod(fp_int* X, fp_int* Y, fp_int* M, fp_int* Z)
zwords = bits2words(min(Ms, Xs + Ys));
hwWords_sz = words2hwords(maxWords_sz);
- if((hwWords_sz<<5) > ESP_HW_RSAMAX_BIT) {
+ if ((hwWords_sz << 5) > ESP_HW_RSAMAX_BIT) {
ESP_LOGE(TAG, "exceeds hw maximum bits");
return -2;
}
@@ -336,20 +412,20 @@ int esp_mp_mulmod(fp_int* X, fp_int* Y, fp_int* M, fp_int* Z)
* accordingly R^2 = 2^(n*32*2)
*/
ret = mp_init_multi(&tmpZ, &r_inv, NULL, NULL, NULL, NULL);
- if(ret == 0 && (ret = esp_get_rinv(&r_inv, M, (hwWords_sz<<6))) != MP_OKAY) {
+ if (ret == 0 && (ret = esp_get_rinv(&r_inv, M, (hwWords_sz << 6))) != MP_OKAY) {
ESP_LOGE(TAG, "calculate r_inv failed.");
mp_clear(&tmpZ);
mp_clear(&r_inv);
return ret;
}
/* lock hw for use */
- if((ret = esp_mp_hw_lock()) != MP_OKAY){
+ if ((ret = esp_mp_hw_lock()) != MP_OKAY) {
mp_clear(&tmpZ);
mp_clear(&r_inv);
return ret;
}
/* Calculate M' */
- if((ret = esp_calc_Mdash(M, 32/* bits */, &mp)) != MP_OKAY) {
+ if ((ret = esp_calc_Mdash(M, 32/* bits */, &mp)) != MP_OKAY) {
ESP_LOGE(TAG, "failed to calculate M dash");
mp_clear(&tmpZ);
mp_clear(&r_inv);
@@ -374,7 +450,7 @@ int esp_mp_mulmod(fp_int* X, fp_int* Y, fp_int* M, fp_int* Z)
* 13. Release the hw engine
*/
- if((ret = esp_mp_hw_wait_clean()) != MP_OKAY){
+ if ((ret = esp_mp_hw_wait_clean()) != MP_OKAY) {
return ret;
}
/* step.1 512 bits => 16 words */
@@ -383,8 +459,11 @@ int esp_mp_mulmod(fp_int* X, fp_int* Y, fp_int* M, fp_int* Z)
/* step.2 write X, M and r_inv into memory */
esp_mpint_to_memblock(RSA_MEM_X_BLOCK_BASE, X, Xs, hwWords_sz);
esp_mpint_to_memblock(RSA_MEM_M_BLOCK_BASE, M, Ms, hwWords_sz);
- esp_mpint_to_memblock(RSA_MEM_Z_BLOCK_BASE, &r_inv, mp_count_bits(&r_inv),
- hwWords_sz);
+ esp_mpint_to_memblock(RSA_MEM_Z_BLOCK_BASE,
+ &r_inv,
+ mp_count_bits(&r_inv),
+ hwWords_sz);
+
/* step.3 write M' into memory */
DPORT_REG_WRITE(RSA_M_DASH_REG, mp);
/* step.4 start process */
@@ -409,11 +488,11 @@ int esp_mp_mulmod(fp_int* X, fp_int* Y, fp_int* M, fp_int* Z)
/* additional steps */
/* this needs for known issue when Z is greater than M */
- if(mp_cmp(&tmpZ, M)==FP_GT) {
- /* Z -= M */
- mp_sub(&tmpZ, M, &tmpZ);
+ if (mp_cmp(&tmpZ, M) == FP_GT) {
+ /* Z -= M */
+ mp_sub(&tmpZ, M, &tmpZ);
}
- if(negcheck) {
+ if (negcheck) {
mp_sub(M, &tmpZ, &tmpZ);
}
@@ -424,7 +503,25 @@ int esp_mp_mulmod(fp_int* X, fp_int* Y, fp_int* M, fp_int* Z)
return ret;
}
-/* Z = X^Y mod M */
+
+/* Large Number Modular Exponentiation
+ *
+ * Z = X^Y mod M
+ *
+ * See Chapter 24:
+ * https://www.espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf
+ *
+ * The operation is based on Montgomery multiplication. Aside from the
+ * arguments X, Y , and M, two additional ones are needed —r and M′
+.* These arguments are calculated in advance by software.
+.*
+.* The RSA Accelerator supports operand lengths of N ∈ {512, 1024, 1536, 2048,
+.* 2560, 3072, 3584, 4096} bits. The bit length of arguments Z, X, Y , M,
+.* and r can be any one from the N set, but all numbers in a calculation must
+.* be of the same length. The bit length of M′ is always 32.
+.*
+.* Note some DH references may use: Y = (G ^ X) mod P
+ */
int esp_mp_exptmod(fp_int* X, fp_int* Y, word32 Ys, fp_int* M, fp_int* Z)
{
int ret = 0;
@@ -444,7 +541,7 @@ int esp_mp_exptmod(fp_int* X, fp_int* Y, word32 Ys, fp_int* M, fp_int* Z)
maxWords_sz = bits2words(max(Xs, max(Ys, Ms)));
hwWords_sz = words2hwords(maxWords_sz);
- if((hwWords_sz<<5) > ESP_HW_RSAMAX_BIT) {
+ if ((hwWords_sz << 5) > ESP_HW_RSAMAX_BIT) {
ESP_LOGE(TAG, "exceeds hw maximum bits");
return -2;
}
@@ -453,19 +550,19 @@ int esp_mp_exptmod(fp_int* X, fp_int* Y, word32 Ys, fp_int* M, fp_int* Z)
* accordingly R^2 = 2^(n*32*2)
*/
ret = mp_init(&r_inv);
- if(ret == 0 && (ret = esp_get_rinv(&r_inv, M, (hwWords_sz<<6))) != MP_OKAY) {
+ if (ret == 0 && (ret = esp_get_rinv(&r_inv, M, (hwWords_sz << 6))) != MP_OKAY) {
ESP_LOGE(TAG, "calculate r_inv failed.");
mp_clear(&r_inv);
return ret;
}
/* lock and init the hw */
- if((ret = esp_mp_hw_lock()) != MP_OKAY) {
+ if ((ret = esp_mp_hw_lock()) != MP_OKAY) {
mp_clear(&r_inv);
return ret;
}
/* calc M' */
/* if Pm is odd, uses mp_montgomery_setup() */
- if((ret = esp_calc_Mdash(M, 32/* bits */, &mp)) != MP_OKAY) {
+ if ((ret = esp_calc_Mdash(M, 32/* bits */, &mp)) != MP_OKAY) {
ESP_LOGE(TAG, "failed to calculate M dash");
mp_clear(&r_inv);
return -1;
@@ -483,7 +580,7 @@ int esp_mp_exptmod(fp_int* X, fp_int* Y, word32 Ys, fp_int* M, fp_int* Z)
* 6. Read the result Z(=Y) from Z_MEM
* 7. Write 1 to INTERRUPT_REG to clear the interrupt.
*/
- if((ret = esp_mp_hw_wait_clean()) != MP_OKAY){
+ if ((ret = esp_mp_hw_wait_clean()) != MP_OKAY) {
return ret;
}
@@ -493,8 +590,10 @@ int esp_mp_exptmod(fp_int* X, fp_int* Y, word32 Ys, fp_int* M, fp_int* Z)
esp_mpint_to_memblock(RSA_MEM_X_BLOCK_BASE, X, Xs, hwWords_sz);
esp_mpint_to_memblock(RSA_MEM_Y_BLOCK_BASE, Y, Ys, hwWords_sz);
esp_mpint_to_memblock(RSA_MEM_M_BLOCK_BASE, M, Ms, hwWords_sz);
- esp_mpint_to_memblock(RSA_MEM_Z_BLOCK_BASE, &r_inv, mp_count_bits(&r_inv),
- hwWords_sz);
+ esp_mpint_to_memblock(RSA_MEM_Z_BLOCK_BASE,
+ &r_inv,
+ mp_count_bits(&r_inv),
+ hwWords_sz);
/* step.3 write M' into memory */
DPORT_REG_WRITE(RSA_M_DASH_REG, mp);
/* step.4 start process */
@@ -512,4 +611,5 @@ int esp_mp_exptmod(fp_int* X, fp_int* Y, word32 Ys, fp_int* M, fp_int* Z)
return ret;
}
#endif /* !NO_RSA || HAVE_ECC */
+
#endif /* (WOLFSS_ESP32WROOM32_CRYPT) && (NO_WOLFSSL_ESP32WROOM32_CRYPT_RES_PRI)*/
diff --git a/wolfcrypt/src/port/Espressif/esp32_sha.c b/wolfcrypt/src/port/Espressif/esp32_sha.c
index 2f8f38fd9..63967da00 100644
--- a/wolfcrypt/src/port/Espressif/esp32_sha.c
+++ b/wolfcrypt/src/port/Espressif/esp32_sha.c
@@ -18,23 +18,28 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
-#include
-#include
-
#ifdef HAVE_CONFIG_H
#include
#endif
-#include
+#include
+/*****************************************************************************/
+/* this entire file content is excluded when NO_SHA, NO_SHA256
+ * or when using WC_SHA384 or WC_SHA512
+ */
#if !defined(NO_SHA) || !defined(NO_SHA256) || defined(WC_SHA384) || \
defined(WC_SHA512)
#include "wolfssl/wolfcrypt/logging.h"
+/* this entire file content is excluded if not using HW hash acceleration */
#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
!defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
+/* TODO this may be chip type dependent: add support for others */
+#include /* ESP32-WROOM */
+
#include
#include
#include
@@ -50,20 +55,29 @@
#endif
static const char* TAG = "wolf_hw_sha";
-/* continue register offset */
-#define CONTINUE_REG_OFFSET (0x04) /* start_reg + 0x04 */
#ifdef NO_SHA
#define WC_SHA_DIGEST_SIZE 20
#endif
+
/* mutex */
#if defined(SINGLE_THREADED)
-static int InUse = 0;
+ static int InUse = 0;
#else
-static wolfSSL_Mutex sha_mutex;
-static int espsha_CryptHwMutexInit = 0;
+ static wolfSSL_Mutex sha_mutex;
+ static int espsha_CryptHwMutexInit = 0;
+
+ #if defined(DEBUG_WOLFSSL)
+ static int this_block_num = 0;
+ #endif
#endif
+
/*
+ * determine the digest size, depending on SHA type.
+ *
+ * See FIPS PUB 180-4, Instruction Section 1.
+ *
+ *
enum SHA_TYPE {
SHA1 = 0,
SHA2_256,
@@ -72,43 +86,112 @@ static int espsha_CryptHwMutexInit = 0;
SHA_INVALID = -1,
};
*/
-static word32 esp_sha_digest_size(enum SHA_TYPE type)
+static word32 wc_esp_sha_digest_size(enum SHA_TYPE type)
{
- ESP_LOGV(TAG, "enter esp_sha_digest_size");
+ ESP_LOGV(TAG, " esp_sha_digest_size");
switch(type){
-#ifndef NO_SHA
- case SHA1:
- return WC_SHA_DIGEST_SIZE;
-#endif
-#ifndef NO_SHA256
- case SHA2_256:
- return WC_SHA256_DIGEST_SIZE;
-#endif
-#ifdef WOLFSSL_SHA384
- case SHA2_384:
- return WC_SHA384_DIGEST_SIZE;
-#endif
-#ifdef WOLFSSL_SHA512
- case SHA2_512:
- return WC_SHA512_DIGEST_SIZE;
-#endif
+ #ifndef NO_SHA
+ case SHA1: /* typically 20 bytes */
+ return WC_SHA_DIGEST_SIZE;
+ #endif
+
+ #ifndef NO_SHA256
+ case SHA2_256: /* typically 32 bytes */
+ return WC_SHA256_DIGEST_SIZE;
+ #endif
+
+ #ifdef WOLFSSL_SHA384
+ case SHA2_384:
+ return WC_SHA384_DIGEST_SIZE;
+ #endif
+
+ #ifdef WOLFSSL_SHA512
+ case SHA2_512: /* typically 64 bytes */
+ return WC_SHA512_DIGEST_SIZE;
+ #endif
+
default:
ESP_LOGE(TAG, "Bad sha type");
return WC_SHA_DIGEST_SIZE;
}
- ESP_LOGV(TAG, "leave esp_sha_digest_size");
+ /* we never get here, as all the above switches should have a return */
}
+
/*
-* wait until engines becomes idle
+* wait until all engines becomes idle
*/
-static void esp_wait_until_idle()
+static void wc_esp_wait_until_idle()
{
- while((DPORT_REG_READ(SHA_1_BUSY_REG) !=0) ||
- (DPORT_REG_READ(SHA_256_BUSY_REG)!=0) ||
- (DPORT_REG_READ(SHA_384_BUSY_REG)!=0) ||
- (DPORT_REG_READ(SHA_512_BUSY_REG)!=0)){ }
+ while((DPORT_REG_READ(SHA_1_BUSY_REG) != 0) ||
+ (DPORT_REG_READ(SHA_256_BUSY_REG) != 0) ||
+ (DPORT_REG_READ(SHA_384_BUSY_REG) != 0) ||
+ (DPORT_REG_READ(SHA_512_BUSY_REG) != 0)) {
+ /* do nothing while waiting. */
+ }
}
+
+/*
+ * hack alert. there really should have been something implemented
+ * in periph_ctrl.c to detect ref_counts[periph] depth.
+ *
+ * since there is not at this time, we have this brute-force method.
+ *
+ * when trying to unwrap an arbitrary depth of peripheral-enable(s),
+ * we'll check the register upon *enable* to see if we actually did.
+ *
+ * Note that enable / disable only occurs when ref_counts[periph] == 0
+ *
+ * TODO: check if this works with other ESP32 platforms ESP32-C3, ESP32-S3, etc
+ */
+int esp_unroll_sha_module_enable(WC_ESP32SHA* ctx)
+{
+ /* if we end up here, there was a prior unexpected fail and
+ * we need to unroll enables */
+ int ret = 0; /* assume success unless proven otherwise */
+ uint32_t this_sha_mask; /* this is the bit-mask for our SHA CLK_EN_REG */
+ int actual_unroll_count = 0;
+ int max_unroll_count = 1000; /* never get stuck in a hardware wait loop */
+
+ this_sha_mask = periph_ll_get_clk_en_mask(PERIPH_SHA_MODULE);
+
+ /* unwind prior calls to THIS ctx. decrement ref_counts[periph] */
+ /* only when ref_counts[periph] == 0 does something actually happen */
+
+ /* once the value we read is a 0 in the DPORT_PERI_CLK_EN_REG bit
+ * then we have fully unrolled the enables via ref_counts[periph]==0 */
+ while ((this_sha_mask & *(uint32_t*)DPORT_PERI_CLK_EN_REG) != 0) {
+ periph_module_disable(PERIPH_SHA_MODULE);
+ actual_unroll_count++;
+ ESP_LOGI(TAG, "unroll not yet successful. try #%d",
+ actual_unroll_count);
+
+ /* 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 */
+ break;
+ }
+ }
+
+ if (ret == 0) {
+ if (ctx->lockDepth != actual_unroll_count) {
+ /* this could be a warning of wonkiness in RTOS environment.
+ * we were successful, but not expected depth count*/
+
+ ESP_LOGE(TAG, "warning lockDepth mismatch.");
+ }
+ ctx->lockDepth = 0;
+ ctx->mode = ESP32_SHA_INIT;
+ }
+ else {
+ ESP_LOGE(TAG, "Failed to unroll after %d attempts.",
+ actual_unroll_count);
+ ctx->mode = ESP32_SHA_SW;
+ }
+ return ret;
+}
+
/*
* lock hw engine.
* this should be called before using engine.
@@ -119,160 +202,375 @@ int esp_sha_try_hw_lock(WC_ESP32SHA* ctx)
ESP_LOGV(TAG, "enter esp_sha_hw_lock");
- /* Init mutex */
+ if (ctx == NULL) {
+ ESP_LOGE(TAG, " esp_sha_try_hw_lock called with NULL ctx");
+ return -1;
+ }
+
+ /* Init mutex
+ *
+ * Note that even single thread mode may calculate hashes
+ * concurrently, so we still need to keep track of the
+ * engine being busy or not.
+ **/
#if defined(SINGLE_THREADED)
if(ctx->mode == ESP32_SHA_INIT) {
if(!InUse) {
ctx->mode = ESP32_SHA_HW;
InUse = 1;
- } else {
+ }
+ else {
ctx->mode = ESP32_SHA_SW;
}
- } else {
+ }
+ else {
/* this should not happens */
ESP_LOGE(TAG, "unexpected error in esp_sha_try_hw_lock.");
return -1;
}
-#else
- if(espsha_CryptHwMutexInit == 0){
+#else /* not defined(SINGLE_THREADED) */
+ /*
+ * there's only one SHA engine for all the hash types
+ * so when any hash is in use, no others can use it.
+ * fall back to SW.
+ **/
+
+ /*
+ * here is some sample code to test the unrolling of sha enables:
+ *
+ periph_module_enable(PERIPH_SHA_MODULE);
+ ctx->lockDepth++;
+ periph_module_enable(PERIPH_SHA_MODULE);
+ ctx->lockDepth++;
+ ctx->mode = ESP32_FAIL_NEED_INIT;
+
+ */
+
+ if (espsha_CryptHwMutexInit == 0) {
+ ESP_LOGV(TAG, "set esp_CryptHwMutexInit");
ret = esp_CryptHwMutexInit(&sha_mutex);
- if(ret == 0) {
+ if (ret == 0) {
espsha_CryptHwMutexInit = 1;
- } else {
- ESP_LOGE(TAG, " mutex initialization failed.");
+ }
+ else {
+ ESP_LOGE(TAG, " mutex initialization failed. revert to software");
ctx->mode = ESP32_SHA_SW;
- return 0;
+ /* espsha_CryptHwMutexInit is still zero */
+ return 0; /* success, just not using HW */
}
}
+
/* check if this sha has been operated as sw or hw, or not yet init */
- if(ctx->mode == ESP32_SHA_INIT){
+ if (ctx->mode == ESP32_SHA_INIT) {
/* try to lock the hw engine */
- if(esp_CryptHwMutexLock(&sha_mutex, (TickType_t)0) == 0) {
- ctx->mode = ESP32_SHA_HW;
- } else {
- ESP_LOGI(TAG, "someone used. hw is locked.....");
- ESP_LOGI(TAG, "the rest of operation will use sw implementation for this sha");
- ctx->mode = ESP32_SHA_SW;
- return 0;
+ ESP_LOGV(TAG, "ESP32_SHA_INIT\n");
+
+ /* we don't wait:
+ * either the engine is free, or we fall back to SW
+ */
+ if (esp_CryptHwMutexLock(&sha_mutex, (TickType_t)0) == 0) {
+ /* check to see if we had a prior fail and need to unroll enables */
+ ret = esp_unroll_sha_module_enable(ctx);
+ ESP_LOGV(TAG, "Hardware Mode, lock depth = %d", ctx->lockDepth);
}
- } else {
- /* this should not happens */
+ else {
+ ESP_LOGI(TAG, ">>>> Hardware in use; Mode REVERT to ESP32_SHA_SW");
+ ctx->mode = ESP32_SHA_SW;
+ return 0; /* success, but revert to SW */
+ }
+ }
+ else {
+ /* this should not happen: called during mode != ESP32_SHA_INIT */
ESP_LOGE(TAG, "unexpected error in esp_sha_try_hw_lock.");
return -1;
}
-#endif
- /* Enable SHA hardware */
- periph_module_enable(PERIPH_SHA_MODULE);
+#endif /* not defined(SINGLE_THREADED) */
+
+ if (ret == 0) {
+ ctx->lockDepth++; /* depth for THIS ctx (there could be others!) */
+ periph_module_enable(PERIPH_SHA_MODULE);
+ ctx->mode = ESP32_SHA_HW;
+ }
+ else {
+ ESP_LOGI(TAG, ">>>> Other problem; Mode REVERT to ESP32_SHA_SW");
+ ctx->mode = ESP32_SHA_SW;
+ }
ESP_LOGV(TAG, "leave esp_sha_hw_lock");
return ret;
-}
+} /* esp_sha_try_hw_lock */
+
/*
-* release hw engine
+* release hw engine. when we don't have it locked, SHA module is DISABLED
*/
-void esp_sha_hw_unlock( void )
+int esp_sha_hw_unlock(WC_ESP32SHA* ctx)
{
ESP_LOGV(TAG, "enter esp_sha_hw_unlock");
/* Disable AES hardware */
periph_module_disable(PERIPH_SHA_MODULE);
-#if defined(SINGLE_THREADED)
- InUse = 0;
-#else
- /* unlock hw engine for next use */
- esp_CryptHwMutexUnLock(&sha_mutex);
-#endif
+
+ #if defined(SINGLE_THREADED)
+ InUse = 0;
+ #else
+ /* unlock hw engine for next use */
+ esp_CryptHwMutexUnLock(&sha_mutex);
+ #endif
+
+ /* we'll keep track of our lock depth.
+ * in case of unexpected results, all the periph_module_disable() calls
+ * and periph_module_disable() need to be unwound.
+ *
+ * see ref_counts[periph] in file: periph_ctrl.c */
+ if (ctx->lockDepth > 0) {
+ ctx->lockDepth--;
+ }
+ else {
+ ctx->lockDepth = 0;
+ }
+
ESP_LOGV(TAG, "leave esp_sha_hw_unlock");
-}
+ return 0;
+} /* esp_sha_hw_unlock */
+
/*
-* start sha process by using hw engine
+* start sha process by using hw engine.
+* assumes register already loaded.
*/
-static void esp_sha_start_process(WC_ESP32SHA* sha, word32 address)
+static int esp_sha_start_process(WC_ESP32SHA* sha)
{
- ESP_LOGV(TAG, "enter esp_sha_start_process");
+ int ret = 0;
+ if (sha == NULL) {
+ return -1;
+ }
+
+ ESP_LOGV(TAG, " enter esp_sha_start_process");
if(sha->isfirstblock){
- /* start first message block */
- DPORT_REG_WRITE(address, 1);
+ /* start registers for first message block
+ * we don't make any relational memory position assumptions.
+ */
+ switch (sha->sha_type) {
+ case SHA1:
+ DPORT_REG_WRITE(SHA_1_START_REG, 1);
+ break;
+
+ case SHA2_256:
+ DPORT_REG_WRITE(SHA_256_START_REG, 1);
+ break;
+
+ #if defined(WOLFSSL_SHA384)
+ case SHA2_384:
+ DPORT_REG_WRITE(SHA_384_START_REG, 1);
+ break;
+ #endif
+
+ #if defined(WOLFSSL_SHA512)
+ case SHA2_512:
+ DPORT_REG_WRITE(SHA_512_START_REG, 1);
+ break;
+ #endif
+
+ default:
+ sha->mode = ESP32_SHA_FAIL_NEED_UNROLL;
+ ret = -1;
+ break;
+ }
+
sha->isfirstblock = 0;
- } else {
- /* CONTINU_REG */
- DPORT_REG_WRITE(address + CONTINUE_REG_OFFSET , 1);
+ ESP_LOGV(TAG, " set sha->isfirstblock = 0");
+
+ #if defined(DEBUG_WOLFSSL)
+ this_block_num = 1; /* one-based counter, just for debug info */
+ #endif
+
+ }
+ else {
+ /* continue */
+ /* continue registers for next message block.
+ * we don't make any relational memory position assumptions
+ * for future chip architecture changes.
+ */
+ switch (sha->sha_type) {
+ case SHA1:
+ DPORT_REG_WRITE(SHA_1_CONTINUE_REG, 1);
+ break;
+
+ case SHA2_256:
+ DPORT_REG_WRITE(SHA_256_CONTINUE_REG, 1);
+ break;
+
+ #if defined(WOLFSSL_SHA384)
+ case SHA2_384:
+ DPORT_REG_WRITE(SHA_384_CONTINUE_REG, 1);
+ break;
+ #endif
+
+ #if defined(WOLFSSL_SHA512)
+ case SHA2_512:
+ DPORT_REG_WRITE(SHA_512_CONTINUE_REG, 1);
+ break;
+ #endif
+
+ default:
+ /* error for unsupported other values */
+ sha->mode = ESP32_SHA_FAIL_NEED_UNROLL;
+ ret = -1;
+ break;
+ }
+ #if defined(DEBUG_WOLFSSL)
+ this_block_num++; /* one-based counter */
+ ESP_LOGV(TAG, " continue block #%d", this_block_num);
+ #endif
+
}
- ESP_LOGV(TAG, "leave esp_sha_start_process");
+ ESP_LOGV(TAG, " leave esp_sha_start_process");
+
+ return ret;
}
+
/*
* process message block
*/
-static void esp_process_block(WC_ESP32SHA* ctx, word32 address,
- const word32* data, word32 len)
+static void wc_esp_process_block(WC_ESP32SHA* ctx, /* see ctx->sha_type */
+ const word32* data,
+ word32 len)
{
int i;
-
- ESP_LOGV(TAG, "enter esp_process_block");
+ int word32_to_save = (len) / (sizeof(word32));
+ ESP_LOGV(TAG, " enter esp_process_block");
+ if (word32_to_save > 0x31) {
+ word32_to_save = 0x31;
+ ESP_LOGE(TAG, " ERROR esp_process_block len exceeds 0x31 words");
+ }
/* check if there are any busy engine */
- esp_wait_until_idle();
- /* load message data into hw */
- for(i=0;i<((len)/(sizeof(word32)));++i){
- DPORT_REG_WRITE(SHA_TEXT_BASE+(i*sizeof(word32)),*(data+i));
+ wc_esp_wait_until_idle();
+
+ /* load [len] words of message data into hw */
+ for (i = 0; i < word32_to_save; i++) {
+ /* by using DPORT_REG_WRITE, we avoid the need
+ * to call __builtin_bswap32 to address endiness
+ *
+ * a useful watch array cast to watch at runtime:
+ * ((uint32_t[32]) (*(volatile uint32_t *)(SHA_TEXT_BASE)))
+ *
+ * Write value to DPORT register (does not require protecting)
+ */
+ DPORT_REG_WRITE(SHA_TEXT_BASE + (i*sizeof(word32)), *(data + i));
+ /* memw confirmed auto inserted by compiler here */
}
- /* notify hw to start process */
- esp_sha_start_process(ctx, address);
- ESP_LOGV(TAG, "leave esp_process_block");
+ /* notify hw to start process
+ * see ctx->sha_type
+ * reg data does not change until we are ready to read */
+ esp_sha_start_process(ctx);
+
+ ESP_LOGV(TAG, " leave esp_process_block");
}
-/*
-* retrieve sha digest from memory
-*/
-static void esp_digest_state(WC_ESP32SHA* ctx, byte* hash, enum SHA_TYPE sha_type)
-{
- /* registers */
- word32 SHA_LOAD_REG = SHA_1_LOAD_REG;
- word32 SHA_BUSY_REG = SHA_1_BUSY_REG;
+/*
+ * retrieve sha digest from memory
+ */
+int wc_esp_digest_state(WC_ESP32SHA* ctx, byte* hash)
+{
ESP_LOGV(TAG, "enter esp_digest_state");
- /* sanity check */
- if(sha_type == SHA_INVALID) {
- ESP_LOGE(TAG, "unexpected error. sha_type is invalid.");
- return;
+ if (ctx == NULL) {
+ return -1;
}
- SHA_LOAD_REG += (sha_type << 4);
- SHA_BUSY_REG += (sha_type << 4);
+ /* sanity check */
+ if (ctx->sha_type == SHA_INVALID) {
+ ctx->mode = ESP32_SHA_FAIL_NEED_UNROLL;
+ ESP_LOGE(TAG, "unexpected error. sha_type is invalid.");
+ return -1;
+ }
- if(ctx->isfirstblock == 1){
- /* no hardware use yet. Nothing to do yet */
- return ;
+ if (ctx == NULL) {
+ return -1;
}
/* wait until idle */
- esp_wait_until_idle();
+ wc_esp_wait_until_idle();
+
+ /* each sha_type register is at a different location */
+ switch (ctx->sha_type) {
+ case SHA1:
+ DPORT_REG_WRITE(SHA_1_LOAD_REG, 1);
+ break;
+
+ case SHA2_256:
+ DPORT_REG_WRITE(SHA_256_LOAD_REG, 1);
+ break;
+
+ #if defined(WOLFSSL_SHA384)
+ case SHA2_384:
+ SHA_LOAD_REG = SHA_384_LOAD_REG;
+ SHA_BUSY_REG = SHA_384_BUSY_REG;
+ break;
+ #endif
+
+ #if defined(WOLFSSL_SHA512)
+ case SHA2_512:
+ DPORT_REG_WRITE(SHA_512_LOAD_REG, 1);
+ break;
+ #endif
+
+ default:
+ ctx->mode = ESP32_SHA_FAIL_NEED_UNROLL;
+ return -1;
+ break;
+ }
+
+
+ if(ctx->isfirstblock == 1){
+ /* no hardware use yet. Nothing to do yet */
+ return 0;
+ }
+
/* LOAD final digest */
- DPORT_REG_WRITE(SHA_LOAD_REG, 1);
- /* wait until done */
- while(DPORT_REG_READ(SHA_BUSY_REG) == 1){ }
- esp_dport_access_read_buffer((word32*)(hash), SHA_TEXT_BASE,
- esp_sha_digest_size(sha_type)/sizeof(word32));
+ wc_esp_wait_until_idle();
+
+ /* MEMW instructions before volatile memory references to guarantee
+ * sequential consistency. At least one MEMW should be executed in
+ * between every load or store to a volatile variable
+ */
+ asm volatile("memw");
+
+ /* put result in hash variable.
+ *
+ * ALERT - hardware specific. See esp_hw_support\port\esp32\dport_access.c
+ *
+ * note we read 4-byte word32's here via DPORT_SEQUENCE_REG_READ
+ *
+ * example:
+ * DPORT_SEQUENCE_REG_READ(address + i * 4);
+ */
+ esp_dport_access_read_buffer(
+ (word32*)(hash), /* the result will be found in hash upon exit */
+ SHA_TEXT_BASE, /* there's a fixed reg addy for all SHA */
+ wc_esp_sha_digest_size(ctx->sha_type) / sizeof(word32) /* # 4-byte */
+ );
#if defined(WOLFSSL_SHA512) || defined(WOLFSSL_SHA384)
- if(sha_type==SHA2_384||sha_type==SHA2_512) {
+ if (ctx->sha_type == SHA2_384 || ctx->sha_type == SHA2_512) {
word32 i;
word32* pwrd1 = (word32*)(hash);
/* swap value */
- for(i = 0; i ctx, SHA_START_REG, (const word32*)data,
- WC_SHA_BLOCK_SIZE);
+ wc_esp_process_block(&sha->ctx, (const word32*)data, WC_SHA_BLOCK_SIZE);
ESP_LOGV(TAG, "leave esp_sha_process");
return ret;
}
+
/*
* retrieve sha1 digest
*/
-int esp_sha_digest_process(struct wc_Sha* sha, byte blockproc)
+int esp_sha_digest_process(struct wc_Sha* sha, byte blockprocess)
{
int ret = 0;
ESP_LOGV(TAG, "enter esp_sha_digest_process");
- if(blockproc) {
- word32 SHA_START_REG = SHA_1_START_REG;
-
- esp_process_block(&sha->ctx, SHA_START_REG, sha->buffer,
- WC_SHA_BLOCK_SIZE);
+ if (blockprocess) {
+ wc_esp_process_block(&sha->ctx, sha->buffer, WC_SHA_BLOCK_SIZE);
}
- esp_digest_state(&sha->ctx, (byte*)sha->digest, SHA1);
+ wc_esp_digest_state(&sha->ctx, (byte*)sha->digest);
ESP_LOGV(TAG, "leave esp_sha_digest_process");
@@ -321,69 +614,79 @@ int esp_sha_digest_process(struct wc_Sha* sha, byte blockproc)
#ifndef NO_SHA256
/*
* sha256 process
+*
+* repeatedly call this for [N] blocks of [WC_SHA256_BLOCK_SIZE] bytes of data
*/
int esp_sha256_process(struct wc_Sha256* sha, const byte* data)
{
int ret = 0;
- word32 SHA_START_REG = SHA_1_START_REG;
- ESP_LOGV(TAG, "enter esp_sha256_process");
+ ESP_LOGV(TAG, " enter esp_sha256_process");
- /* start register offset */
- SHA_START_REG += (SHA2_256 << 4);
+ if ((&sha->ctx)->sha_type == SHA2_256) {
+#if defined(DEBUG_WOLFSSL_VERBOSE)
+ ESP_LOGV(TAG, " confirmed sha type call match");
+#endif
+ }
+ else {
+ ret = -1;
+ ESP_LOGE(TAG, " ERROR sha type call mismatch");
+ }
- esp_process_block(&sha->ctx, SHA_START_REG, (const word32*)data,
- WC_SHA256_BLOCK_SIZE);
+ wc_esp_process_block(&sha->ctx, (const word32*)data, WC_SHA256_BLOCK_SIZE);
- ESP_LOGV(TAG, "leave esp_sha256_process");
+ ESP_LOGV(TAG, " leave esp_sha256_process");
return ret;
}
+
/*
* retrieve sha256 digest
+*
+* note that wc_Sha256Final() in sha256.c expects to need to reverse byte
+* order, even though we could have returned them in the right order.
*/
-int esp_sha256_digest_process(struct wc_Sha256* sha, byte blockproc)
+int esp_sha256_digest_process(struct wc_Sha256* sha, byte blockprocess)
{
int ret = 0;
ESP_LOGV(TAG, "enter esp_sha256_digest_process");
- if(blockproc) {
- word32 SHA_START_REG = SHA_1_START_REG + (SHA2_256 << 4);
+ if(blockprocess) {
- esp_process_block(&sha->ctx, SHA_START_REG, sha->buffer,
- WC_SHA256_BLOCK_SIZE);
+ wc_esp_process_block(&sha->ctx, sha->buffer, WC_SHA256_BLOCK_SIZE);
}
- esp_digest_state(&sha->ctx, (byte*)sha->digest, SHA2_256);
+ wc_esp_digest_state(&sha->ctx, (byte*)sha->digest);
ESP_LOGV(TAG, "leave esp_sha256_digest_process");
return ret;
}
+
+
#endif /* NO_SHA256 */
#if defined(WOLFSSL_SHA512) || defined(WOLFSSL_SHA384)
/*
-* sha512 proess. this is used for sha384 too.
+* sha512 process. this is used for sha384 too.
*/
void esp_sha512_block(struct wc_Sha512* sha, const word32* data, byte isfinal)
{
- enum SHA_TYPE sha_type = sha->ctx.sha_type;
- word32 SHA_START_REG = SHA_1_START_REG;
-
ESP_LOGV(TAG, "enter esp_sha512_block");
/* start register offset */
- SHA_START_REG += (sha_type << 4);
if(sha->ctx.mode == ESP32_SHA_SW){
ByteReverseWords64(sha->buffer, sha->buffer,
WC_SHA512_BLOCK_SIZE);
- if(isfinal){
- sha->buffer[WC_SHA512_BLOCK_SIZE / sizeof(word64) - 2] = sha->hiLen;
- sha->buffer[WC_SHA512_BLOCK_SIZE / sizeof(word64) - 1] = sha->loLen;
+ if(isfinal) {
+ sha->buffer[WC_SHA512_BLOCK_SIZE / sizeof(word64) - 2] =
+ sha->hiLen;
+ sha->buffer[WC_SHA512_BLOCK_SIZE / sizeof(word64) - 1] =
+ sha->loLen;
}
- } else {
+ }
+ else {
ByteReverseWords((word32*)sha->buffer, (word32*)sha->buffer,
WC_SHA512_BLOCK_SIZE);
if(isfinal){
@@ -393,7 +696,7 @@ void esp_sha512_block(struct wc_Sha512* sha, const word32* data, byte isfinal)
rotlFixed64(sha->loLen, 32U);
}
- esp_process_block(&sha->ctx, SHA_START_REG, data, WC_SHA512_BLOCK_SIZE);
+ wc_esp_process_block(&sha->ctx, data, WC_SHA512_BLOCK_SIZE);
}
ESP_LOGV(TAG, "leave esp_sha512_block");
}
@@ -424,7 +727,7 @@ int esp_sha512_digest_process(struct wc_Sha512* sha, byte blockproc)
esp_sha512_block(sha, data, 1);
}
if(sha->ctx.mode != ESP32_SHA_SW)
- esp_digest_state(&sha->ctx, (byte*)sha->digest, sha->ctx.sha_type);
+ wc_esp_digest_state(&sha->ctx, (byte*)sha->digest);
ESP_LOGV(TAG, "leave esp_sha512_digest_process");
return 0;
diff --git a/wolfcrypt/src/port/Espressif/esp32_util.c b/wolfcrypt/src/port/Espressif/esp32_util.c
index d73cd2fe8..90d3c617e 100644
--- a/wolfcrypt/src/port/Espressif/esp32_util.c
+++ b/wolfcrypt/src/port/Espressif/esp32_util.c
@@ -1,6 +1,6 @@
/* esp32_util.c
*
- * Copyright (C) 2006-2021 wolfSSL Inc.
+ * Copyright (C) 2006-2022 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
@@ -26,21 +26,57 @@
#include
#include
-
+#include
+/*
+ * initialize our mutex used to lock hardware access
+ *
+ * returns:
+ * 0 upon success,
+ * BAD_MUTEX_E for null mutex
+ * other value from wc_InitMutex()
+ *
+ */
int esp_CryptHwMutexInit(wolfSSL_Mutex* mutex) {
+ if (mutex == NULL) {
+ return BAD_MUTEX_E;
+ }
+
return wc_InitMutex(mutex);
}
+/*
+ * call the ESP-IDF mutex lock; xSemaphoreTake
+ *
+ */
int esp_CryptHwMutexLock(wolfSSL_Mutex* mutex, TickType_t xBlockTime) {
+ if (mutex == NULL) {
+ WOLFSSL_ERROR_MSG("esp_CryptHwMutexLock called with null mutex");
+ return BAD_MUTEX_E;
+ }
+
#ifdef SINGLE_THREADED
- return wc_LockMutex(mutex);
+ return wc_LockMutex(mutex); /* xSemaphoreTake take with portMAX_DELAY */
#else
return ((xSemaphoreTake( *mutex, xBlockTime ) == pdTRUE) ? 0 : BAD_MUTEX_E);
#endif
}
+/*
+ * call the ESP-IDF mutex UNlock; xSemaphoreGive
+ *
+ */
int esp_CryptHwMutexUnLock(wolfSSL_Mutex* mutex) {
+ if (mutex == NULL) {
+ WOLFSSL_ERROR_MSG("esp_CryptHwMutexLock called with null mutex");
+ return BAD_MUTEX_E;
+ }
+
+#ifdef SINGLE_THREADED
return wc_UnLockMutex(mutex);
+#else
+ xSemaphoreGive(*mutex);
+ return 0;
+#endif
}
#endif
diff --git a/wolfcrypt/src/sha.c b/wolfcrypt/src/sha.c
index 8113997fa..8a2cece1f 100644
--- a/wolfcrypt/src/sha.c
+++ b/wolfcrypt/src/sha.c
@@ -1,6 +1,6 @@
/* sha.c
*
- * Copyright (C) 2006-2021 wolfSSL Inc.
+ * Copyright (C) 2006-2022 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
@@ -311,14 +311,15 @@
sha->ctx.isfirstblock = 1;
sha->ctx.sha_type = SHA1;
if(sha->ctx.mode == ESP32_SHA_HW){
+ sha->ctx.lockDepth = 0;
/* release hw engine */
- esp_sha_hw_unlock();
+ esp_sha_hw_unlock(&(sha->ctx));
}
/* always set mode as INIT
* whether using HW or SW is determined at first call of update()
*/
sha->ctx.mode = ESP32_SHA_INIT;
-
+ sha->ctx.lockDepth = 0;
return ret;
}
@@ -538,6 +539,7 @@ int wc_InitSha_ex(wc_Sha* sha, void* heap, int devId)
!defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
sha->ctx.mode = ESP32_SHA_INIT;
sha->ctx.isfirstblock = 1;
+ sha->ctx.lockDepth = 0; /* keep track of how many times lock is called */
#endif
ret = InitSha(sha);
if (ret != 0)
@@ -616,7 +618,8 @@ int wc_ShaUpdate(wc_Sha* sha, const byte* data, word32 len)
}
if (sha->ctx.mode == ESP32_SHA_SW) {
ret = XTRANSFORM(sha, (const byte*)local);
- } else {
+ }
+ else {
esp_sha_process(sha, (const byte*)local);
}
#else
@@ -670,7 +673,8 @@ int wc_ShaUpdate(wc_Sha* sha, const byte* data, word32 len)
}
if (sha->ctx.mode == ESP32_SHA_SW){
ret = XTRANSFORM(sha, (const byte*)local32);
- } else {
+ }
+ else {
esp_sha_process(sha, (const byte*)local32);
}
#else
@@ -753,7 +757,8 @@ int wc_ShaFinal(wc_Sha* sha, byte* hash)
}
if (sha->ctx.mode == ESP32_SHA_SW) {
ret = XTRANSFORM(sha, (const byte*)local);
- } else {
+ }
+ else {
ret = esp_sha_process(sha, (const byte*)local);
}
#else
@@ -793,7 +798,8 @@ int wc_ShaFinal(wc_Sha* sha, byte* hash)
}
if (sha->ctx.mode == ESP32_SHA_SW) {
ret = XTRANSFORM(sha, (const byte*)local);
- } else {
+ }
+ else {
ret = esp_sha_digest_process(sha, 1);
}
#else
@@ -886,13 +892,16 @@ int wc_ShaGetHash(wc_Sha* sha, byte* hash)
if(sha->ctx.mode == ESP32_SHA_INIT){
esp_sha_try_hw_lock(&sha->ctx);
}
- if(sha->ctx.mode != ESP32_SHA_SW)
+ if (sha->ctx.mode != ESP32_SHA_SW) {
+ /* TODO check SW/HW logic */
esp_sha_digest_process(sha, 0);
+ }
#endif
ret = wc_ShaCopy(sha, &tmpSha);
if (ret == 0) {
- ret = wc_ShaFinal(&tmpSha, hash);
+ /* if HW failed, use SW */
+ ret = wc_ShaFinal(&tmpSha, hash);
#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
!defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
sha->ctx.mode = ESP32_SHA_SW;
diff --git a/wolfcrypt/src/sha256.c b/wolfcrypt/src/sha256.c
index 6da015153..5a1946645 100644
--- a/wolfcrypt/src/sha256.c
+++ b/wolfcrypt/src/sha256.c
@@ -1,6 +1,6 @@
/* sha256.c
*
- * Copyright (C) 2006-2021 wolfSSL Inc.
+ * Copyright (C) 2006-2022 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
@@ -19,7 +19,12 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
-/* For more info on the algorithm, see https://tools.ietf.org/html/rfc6234 */
+/* For more info on the algorithm, see https://tools.ietf.org/html/rfc6234
+ *
+ * For more information on NIST FIPS PUB 180-4, see
+ * https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf
+ */
+
/*
DESCRIPTION
@@ -28,7 +33,11 @@ SHA-256 performs processing on message blocks to produce a final hash digest
output. It can be used to hash a message, M, having a length of L bits,
where 0 <= L < 2^64.
+Note that in some cases, hardware acceleration may be enabled, depending
+on the specific device platform.
+
*/
+
#ifdef HAVE_CONFIG_H
#include
#endif
@@ -74,6 +83,19 @@ where 0 <= L < 2^64.
#include
#endif
+/* determine if we are using Espressif SHA hardware acceleration */
+#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
+ !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
+ /* define a single keyword for simplicity & readability
+ *
+ * by default the HW acceleration is on for ESP32-WROOM32
+ * but individual components can be turned off.
+ */
+ #define WOLFSSL_USE_ESP32WROOM32_CRYPT_HASH_HW
+#else
+ #undef USE_ESP32WROOM32_CRYPT_HASH
+#endif
+
/* fips wrapper calls, user can call direct */
#if defined(HAVE_FIPS) && \
(!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))
@@ -694,14 +716,17 @@ static int InitSha256(wc_Sha256* sha256)
return ret;
}
-#elif defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
- !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
+#elif defined(WOLFSSL_USE_ESP32WROOM32_CRYPT_HASH_HW)
+ /* HW may fail since there's only one, so we still need SW */
#define NEED_SOFT_SHA256
+ /*
+ * soft SHA needs initialization digest, but HW does not.
+ */
static int InitSha256(wc_Sha256* sha256)
{
- int ret = 0;
+ int ret = 0; /* zero = success */
if (sha256 == NULL)
return BAD_FUNC_ARG;
@@ -725,8 +750,9 @@ static int InitSha256(wc_Sha256* sha256)
sha256->ctx.sha_type = SHA2_256;
if(sha256->ctx.mode == ESP32_SHA_HW) {
/* release hw */
- esp_sha_hw_unlock();
+ esp_sha_hw_unlock(&(sha256->ctx));
}
+
/* always set mode as INIT
* whether using HW or SW is determined at first call of update()
*/
@@ -734,9 +760,13 @@ static int InitSha256(wc_Sha256* sha256)
return ret;
}
+
+ /*
+ * wolfCrypt InitSha256 external wrapper
+ */
int wc_InitSha256_ex(wc_Sha256* sha256, void* heap, int devId)
{
- int ret = 0;
+ int ret = 0; /* zero = success */
if (sha256 == NULL)
return BAD_FUNC_ARG;
@@ -744,6 +774,7 @@ static int InitSha256(wc_Sha256* sha256)
XMEMSET(sha256, 0, sizeof(wc_Sha256));
sha256->ctx.mode = ESP32_SHA_INIT;
sha256->ctx.isfirstblock = 1;
+ sha256->ctx.lockDepth = 0; /* we'll keep track of our own lock depth */
(void)devId;
ret = InitSha256(sha256);
@@ -786,7 +817,6 @@ static int InitSha256(wc_Sha256* sha256)
int ret = 0;
if (sha256 == NULL)
return BAD_FUNC_ARG;
-
ret = InitSha256(sha256);
if (ret != 0)
return ret;
@@ -1052,14 +1082,16 @@ static int InitSha256(wc_Sha256* sha256)
}
#endif
- #if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
- !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
- if (sha256->ctx.mode == ESP32_SHA_INIT){
+ #if defined(WOLFSSL_USE_ESP32WROOM32_CRYPT_HASH_HW)
+ if (sha256->ctx.mode == ESP32_SHA_INIT ||
+ sha256->ctx.mode == ESP32_SHA_FAIL_NEED_UNROLL) {
esp_sha_try_hw_lock(&sha256->ctx);
}
- if (sha256->ctx.mode == ESP32_SHA_SW){
+
+ if (sha256->ctx.mode == ESP32_SHA_SW) {
ret = XTRANSFORM(sha256, (const byte*)local);
- } else {
+ }
+ else {
esp_sha256_process(sha256, (const byte*)local);
}
#else
@@ -1129,17 +1161,17 @@ static int InitSha256(wc_Sha256* sha256)
}
#endif
- #if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
- !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
+ #if defined(WOLFSSL_USE_ESP32WROOM32_CRYPT_HASH_HW)
if (sha256->ctx.mode == ESP32_SHA_INIT){
esp_sha_try_hw_lock(&sha256->ctx);
}
- if (sha256->ctx.mode == ESP32_SHA_SW){
+ if (sha256->ctx.mode == ESP32_SHA_SW) {
ret = XTRANSFORM(sha256, (const byte*)local32);
- } else {
+ }
+ else {
esp_sha256_process(sha256, (const byte*)local32);
}
- #else
+#else
ret = XTRANSFORM(sha256, (const byte*)local32);
#endif
@@ -1223,14 +1255,14 @@ static int InitSha256(wc_Sha256* sha256)
}
#endif
- #if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
- !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
+ #if defined(WOLFSSL_USE_ESP32WROOM32_CRYPT_HASH_HW)
if (sha256->ctx.mode == ESP32_SHA_INIT) {
esp_sha_try_hw_lock(&sha256->ctx);
}
if (sha256->ctx.mode == ESP32_SHA_SW) {
ret = XTRANSFORM(sha256, (const byte*)local);
- } else {
+ }
+ else {
ret = esp_sha256_process(sha256, (const byte*)local);
}
#else
@@ -1280,14 +1312,14 @@ static int InitSha256(wc_Sha256* sha256)
}
#endif
- #if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
- !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
+ #if defined(WOLFSSL_USE_ESP32WROOM32_CRYPT_HASH_HW)
if (sha256->ctx.mode == ESP32_SHA_INIT) {
esp_sha_try_hw_lock(&sha256->ctx);
}
if (sha256->ctx.mode == ESP32_SHA_SW) {
ret = XTRANSFORM(sha256, (const byte*)local);
- } else {
+ }
+ else {
ret = esp_sha256_digest_process(sha256, 1);
}
#else
@@ -1385,7 +1417,6 @@ static int InitSha256(wc_Sha256* sha256)
{
if (sha224 == NULL)
return BAD_FUNC_ARG;
-
(void)devId;
(void)heap;
@@ -1848,9 +1879,15 @@ int wc_Sha256GetHash(wc_Sha256* sha256, byte* hash)
if (sha256 == NULL || hash == NULL)
return BAD_FUNC_ARG;
-#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
- !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
- if(sha256->ctx.mode == ESP32_SHA_INIT){
+#if defined(WOLFSSL_USE_ESP32WROOM32_CRYPT_HASH_HW)
+
+ /* ESP32 hardware can only handle only 1 active hardware hashing
+ * at a time. If the mutex lock is acquired the first time then
+ * that Sha256 instance has exclusive access to hardware. The
+ * final or free needs to release the mutex. Operations that
+ * do not get the lock fallback to software based Sha256 */
+
+ if(sha256->ctx.mode == ESP32_SHA_INIT){
esp_sha_try_hw_lock(&sha256->ctx);
}
if(sha256->ctx.mode == ESP32_SHA_HW)
@@ -1861,13 +1898,20 @@ int wc_Sha256GetHash(wc_Sha256* sha256, byte* hash)
ret = wc_Sha256Copy(sha256, &tmpSha256);
if (ret == 0) {
ret = wc_Sha256Final(&tmpSha256, hash);
-#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
- !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
+
+#if defined(WOLFSSL_USE_ESP32WROOM32_CRYPT_HASH_HW)
+ {
sha256->ctx.mode = ESP32_SHA_SW;
+ }
#endif
wc_Sha256Free(&tmpSha256);
}
+
+#if defined(WOLFSSL_USE_ESP32WROOM32_CRYPT_HASH_HW)
+ /* TODO: Make sure the ESP32 crypto mutex is released (in case final is not
+ * called */
+#endif
return ret;
}
int wc_Sha256Copy(wc_Sha256* src, wc_Sha256* dst)
@@ -1893,12 +1937,14 @@ int wc_Sha256Copy(wc_Sha256* src, wc_Sha256* dst)
#ifdef WOLFSSL_PIC32MZ_HASH
ret = wc_Pic32HashCopy(&src->cache, &dst->cache);
#endif
-#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
- !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
- dst->ctx.mode = src->ctx.mode;
- dst->ctx.isfirstblock = src->ctx.isfirstblock;
- dst->ctx.sha_type = src->ctx.sha_type;
+
+#if defined(WOLFSSL_USE_ESP32WROOM32_CRYPT_HASH_HW)
+ dst->ctx.mode = src->ctx.mode;
+ dst->ctx.isfirstblock = src->ctx.isfirstblock;
+ dst->ctx.sha_type = src->ctx.sha_type;
+ dst->ctx.lockDepth = src->ctx.lockDepth;
#endif
+
#ifdef WOLFSSL_HASH_FLAGS
dst->flags |= WC_HASH_FLAG_ISCOPY;
#endif
diff --git a/wolfcrypt/src/sha512.c b/wolfcrypt/src/sha512.c
index f6c863665..94164334a 100644
--- a/wolfcrypt/src/sha512.c
+++ b/wolfcrypt/src/sha512.c
@@ -285,7 +285,7 @@ static int InitSha512(wc_Sha512* sha512)
sha512->ctx.isfirstblock = 1;
if(sha512->ctx.mode == ESP32_SHA_HW) {
/* release hw */
- esp_sha_hw_unlock();
+ esp_sha_hw_unlock(&(sha512->ctx));
}
/* always set mode as INIT
* whether using HW or SW is determined at first call of update()
@@ -332,7 +332,7 @@ static int InitSha512_224(wc_Sha512* sha512)
sha512->ctx.isfirstblock = 1;
if(sha512->ctx.mode == ESP32_SHA_HW) {
/* release hw */
- esp_sha_hw_unlock();
+ esp_sha_hw_unlock(&(sha512->ctx));
}
/* always set mode as INIT
* whether using HW or SW is determined at first call of update()
@@ -381,7 +381,7 @@ static int InitSha512_256(wc_Sha512* sha512)
sha512->ctx.isfirstblock = 1;
if(sha512->ctx.mode == ESP32_SHA_HW) {
/* release hw */
- esp_sha_hw_unlock();
+ esp_sha_hw_unlock(&(sha512->ctx));
}
/* always set mode as INIT
* whether using HW or SW is determined at first call of update()
@@ -1310,7 +1310,7 @@ static int InitSha384(wc_Sha384* sha384)
sha384->ctx.isfirstblock = 1;
if(sha384->ctx.mode == ESP32_SHA_HW) {
/* release hw */
- esp_sha_hw_unlock();
+ esp_sha_hw_unlock(&(sha512->ctx));
}
/* always set mode as INIT
* whether using HW or SW is determined at first call of update()
diff --git a/wolfssl/wolfcrypt/port/Espressif/esp32-crypt.h b/wolfssl/wolfcrypt/port/Espressif/esp32-crypt.h
index f64d616cb..9b3b79a71 100644
--- a/wolfssl/wolfcrypt/port/Espressif/esp32-crypt.h
+++ b/wolfssl/wolfcrypt/port/Espressif/esp32-crypt.h
@@ -22,39 +22,44 @@
#define __ESP32_CRYPT_H__
+#ifdef WOLFSSL_USER_SETTINGS
+ #include "user_settings.h"
+#endif
+
#include "esp_idf_version.h"
#include "esp_types.h"
#include "esp_log.h"
#ifdef WOLFSSL_ESP32WROOM32_CRYPT_DEBUG
-#undef LOG_LOCAL_LEVEL
-#define LOG_LOCAL_LEVEL ESP_LOG_DEBUG
+ #undef LOG_LOCAL_LEVEL
+ #define LOG_LOCAL_LEVEL ESP_LOG_DEBUG
#else
-#undef LOG_LOCAL_LEVEL
-#define LOG_LOCAL_LEVEL ESP_LOG_ERROR
+ #undef LOG_LOCAL_LEVEL
+ #define LOG_LOCAL_LEVEL ESP_LOG_DEBUG
#endif
#include
#include "soc/dport_reg.h"
#include "soc/hwcrypto_reg.h"
+
#if ESP_IDF_VERSION_MAJOR < 5
-#include "soc/cpu.h"
+ #include "soc/cpu.h"
#endif
#if ESP_IDF_VERSION_MAJOR >= 5
- #include "esp_private/periph_ctrl.h"
+ #include "esp_private/periph_ctrl.h"
#else
- #include "driver/periph_ctrl.h"
+ #include "driver/periph_ctrl.h"
#endif
#if ESP_IDF_VERSION_MAJOR >= 4
- #include
+ #include
#else
- #include
+ #include
#endif
#ifdef __cplusplus
-extern "C" {
+ extern "C" {
#endif
int esp_CryptHwMutexInit(wolfSSL_Mutex* mutex);
@@ -63,31 +68,31 @@ int esp_CryptHwMutexUnLock(wolfSSL_Mutex* mutex);
#ifndef NO_AES
-#if ESP_IDF_VERSION_MAJOR >= 4
-#include "esp32/rom/aes.h"
-#else
-#include "rom/aes.h"
-#endif
+ #if ESP_IDF_VERSION_MAJOR >= 4
+ #include "esp32/rom/aes.h"
+ #else
+ #include "rom/aes.h"
+ #endif
-typedef enum tagES32_AES_PROCESS {
- ESP32_AES_LOCKHW = 1,
- ESP32_AES_UPDATEKEY_ENCRYPT = 2,
- ESP32_AES_UPDATEKEY_DECRYPT = 3,
- ESP32_AES_UNLOCKHW = 4
-} ESP32_AESPROCESS;
+ typedef enum tagES32_AES_PROCESS {
+ ESP32_AES_LOCKHW = 1,
+ ESP32_AES_UPDATEKEY_ENCRYPT = 2,
+ ESP32_AES_UPDATEKEY_DECRYPT = 3,
+ ESP32_AES_UNLOCKHW = 4
+ } ESP32_AESPROCESS;
-struct Aes;
-int wc_esp32AesCbcEncrypt(struct Aes* aes, byte* out, const byte* in, word32 sz);
-int wc_esp32AesCbcDecrypt(struct Aes* aes, byte* out, const byte* in, word32 sz);
-int wc_esp32AesEncrypt(struct Aes *aes, const byte* in, byte* out);
-int wc_esp32AesDecrypt(struct Aes *aes, const byte* in, byte* out);
+ struct Aes; /* see aes.h */
+ int wc_esp32AesCbcEncrypt(struct Aes* aes, byte* out, const byte* in, word32 sz);
+ int wc_esp32AesCbcDecrypt(struct Aes* aes, byte* out, const byte* in, word32 sz);
+ int wc_esp32AesEncrypt(struct Aes *aes, const byte* in, byte* out);
+ int wc_esp32AesDecrypt(struct Aes *aes, const byte* in, byte* out);
#endif
#ifdef WOLFSSL_ESP32WROOM32_CRYPT_DEBUG
-void wc_esp32TimerStart();
-uint64_t wc_esp32elapsedTime();
+ void wc_esp32TimerStart();
+ uint64_t wc_esp32elapsedTime();
#endif /* WOLFSSL_ESP32WROOM32_CRYPT_DEBUG */
@@ -95,66 +100,107 @@ uint64_t wc_esp32elapsedTime();
defined(WOLFSSL_SHA512)) && \
!defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
-/* 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
-#include "esp32/rom/sha.h"
-#else
-#include "rom/sha.h"
-#endif
-#undef SHA_CTX
+ /* RAW hash function APIs are not implemented with esp32 hardware acceleration*/
+ #define WOLFSSL_NO_HASH_RAW
+ #define SHA_CTX ETS_SHAContext
-typedef enum {
- ESP32_SHA_INIT = 0,
- ESP32_SHA_HW = 1,
- ESP32_SHA_SW = 2,
-} ESP32_DOSHA;
+ #if ESP_IDF_VERSION_MAJOR >= 4
+ #include "esp32/rom/sha.h"
+ #else
+ #include "rom/sha.h"
+ #endif
-typedef struct {
- byte isfirstblock;
- /* 0 , 1 hard, 2 soft */
- byte mode;
- /* sha_type */
- enum SHA_TYPE sha_type;
-} WC_ESP32SHA;
+ #undef SHA_CTX
-int esp_sha_try_hw_lock(WC_ESP32SHA* ctx);
-void esp_sha_hw_unlock( void );
+ typedef enum {
+ ESP32_SHA_INIT = 0,
+ ESP32_SHA_HW = 1,
+ ESP32_SHA_SW = 2,
+ ESP32_SHA_FAIL_NEED_UNROLL = -1
+ } ESP32_MODE;
-struct wc_Sha;
-int esp_sha_digest_process(struct wc_Sha* sha, byte bockprocess);
-int esp_sha_process(struct wc_Sha* sha, const byte* data);
+ typedef struct {
+ byte isfirstblock;
-#ifndef NO_SHA256
- struct wc_Sha256;
- int esp_sha256_digest_process(struct wc_Sha256* sha, byte bockprocess);
- int esp_sha256_process(struct wc_Sha256* sha, const byte* data);
-#endif
+ ESP32_MODE mode; /* typically 0 init, 1 HW, 2 SW */
-#if defined(WOLFSSL_SHA512) || defined(WOLFSSL_SHA384)
- struct wc_Sha512;
- int esp_sha512_process(struct wc_Sha512* sha);
- int esp_sha512_digest_process(struct wc_Sha512* sha, byte blockproc);
-#endif
+ /* we'll keep track of our own locks.
+ * actual enable/disable only occurs for ref_counts[periph] == 0 */
+ int lockDepth; /* see ref_counts[periph] in periph_ctrl.c */
+
+ enum SHA_TYPE sha_type;
+ } WC_ESP32SHA;
+
+ int esp_sha_try_hw_lock(WC_ESP32SHA* ctx);
+ int esp_sha_hw_unlock(WC_ESP32SHA* ctx);
+
+ struct wc_Sha;
+ int esp_sha_digest_process(struct wc_Sha* sha, byte blockprocess);
+ int esp_sha_process(struct wc_Sha* sha, const byte* data);
+
+ #ifndef NO_SHA256
+ struct wc_Sha256;
+ int esp_sha256_digest_process(struct wc_Sha256* sha, byte blockprocess);
+ int esp_sha256_process(struct wc_Sha256* sha, const byte* data);
+ int esp32_Transform_Sha256_demo(struct wc_Sha256* sha256, const byte* data);
+
+
+ #endif
+
+ /* TODO do we really call esp_sha512_process for WOLFSSL_SHA384 ? */
+ #if defined(WOLFSSL_SHA512) || defined(WOLFSSL_SHA384)
+ struct wc_Sha512;
+ int esp_sha512_process(struct wc_Sha512* sha);
+ int esp_sha512_digest_process(struct wc_Sha512* sha, byte blockproc);
+ #endif
#endif /* NO_SHA && */
+
#if !defined(NO_RSA) || defined(HAVE_ECC)
-#if !defined(ESP_RSA_TIMEOUT_CNT)
- #define ESP_RSA_TIMEOUT_CNT 0x249F00
-#endif
+ #if !defined(ESP_RSA_TIMEOUT_CNT)
+ #define ESP_RSA_TIMEOUT_CNT 0x249F00
+ #endif
-struct fp_int;
-int esp_mp_mul(struct fp_int* X, struct fp_int* Y, struct fp_int* Z);
-int esp_mp_exptmod(struct fp_int* G, struct fp_int* X, word32 Xbits, struct fp_int* P,
- struct fp_int* Y);
-int esp_mp_mulmod(struct fp_int* X, struct fp_int* Y, struct fp_int* M,
- struct fp_int* Z);
+ /* operands can be up to 4096 bits long.
+ * here we store the bits in wolfSSL fp_int struct.
+ * see wolfCrypt tfm.h
+ */
+ struct fp_int;
+
+
+ /*
+ * The parameter names in the Espressif implementation are arbitrary.
+ *
+ * The wolfSSL names come from DH: Y=G^x mod M (see wolfcrypt/tfm.h)
+ *
+ * G=base, X is the private exponent, Y is the public value w
+ **/
+
+ /* Z = (X ^ Y) mod M : Espressif generic notation */
+ /* Y = (G ^ X) mod P : wolfSSL DH reference notation */
+ int esp_mp_exptmod(struct fp_int* X, /* G */
+ struct fp_int* Y, /* X */
+ word32 Xbits, /* Ys typically = fp_count_bits (X) */
+ struct fp_int* M, /* P */
+ struct fp_int* Z); /* Y */
+
+ /* Z = X * Y */
+ int esp_mp_mul(struct fp_int* X,
+ struct fp_int* Y,
+ struct fp_int* Z);
+
+
+ /* Z = X * Y (mod M) */
+ int esp_mp_mulmod(struct fp_int* X,
+ struct fp_int* Y,
+ struct fp_int* M,
+ struct fp_int* Z);
#endif /* NO_RSA || HAVE_ECC*/
+/* end c++ wrapper */
#ifdef __cplusplus
}
#endif
diff --git a/wolfssl/wolfcrypt/types.h b/wolfssl/wolfcrypt/types.h
index 13f8d3812..cac7558ff 100644
--- a/wolfssl/wolfcrypt/types.h
+++ b/wolfssl/wolfcrypt/types.h
@@ -1,6 +1,6 @@
/* types.h
*
- * Copyright (C) 2006-2021 wolfSSL Inc.
+ * Copyright (C) 2006-2022 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
@@ -714,7 +714,7 @@ typedef struct w64wrapper {
/* In cases when truncation is expected the caller needs*/
/* to check the return value from the function so that */
/* compiler doesn't complain. */
- /* xtensa-esp32-elf v8.2.0 warns trancation at */
+ /* xtensa-esp32-elf v8.2.0 warns truncation at */
/* GetAsnTimeString() */
static WC_INLINE
int _xsnprintf_(char *s, size_t n, const char *format, ...)