diff --git a/IDE/Espressif/ESP-IDF/.gitignore b/IDE/Espressif/ESP-IDF/.gitignore new file mode 100644 index 0000000000..1babb6fc39 --- /dev/null +++ b/IDE/Espressif/ESP-IDF/.gitignore @@ -0,0 +1,2 @@ +# Exclude sdkconfig backups created by idf.py etc (e.g., sdkconfig.old). +*.old diff --git a/IDE/Espressif/ESP-IDF/examples/wolfssl_test/main/main.c b/IDE/Espressif/ESP-IDF/examples/wolfssl_test/main/main.c index 01538f72e3..b8993cb481 100644 --- a/IDE/Espressif/ESP-IDF/examples/wolfssl_test/main/main.c +++ b/IDE/Espressif/ESP-IDF/examples/wolfssl_test/main/main.c @@ -177,8 +177,6 @@ void app_main(void) #error "ESP32WROOM32_CRYPT not yet supported on ESP32-C3" #elif defined(CONFIG_IDF_TARGET_ESP32S2) #error "ESP32WROOM32_CRYPT not yet supported on ESP32-S2" - #elif defined(CONFIG_IDF_TARGET_ESP32S3) - #error "ESP32WROOM32_CRYPT not yet supported on ESP32-S3" #else ESP_LOGI(TAG, "ESP32WROOM32_CRYPT is enabled."); #endif diff --git a/IDE/Espressif/ESP-IDF/setup_win.bat b/IDE/Espressif/ESP-IDF/setup_win.bat index 2e279ad947..fd0372d127 100644 --- a/IDE/Espressif/ESP-IDF/setup_win.bat +++ b/IDE/Espressif/ESP-IDF/setup_win.bat @@ -28,15 +28,19 @@ if NOT EXIST "user_settings.h" ( goto :ERR ) +:: Get argument 1 sans quotes +set Arg1=%~1 + :: see if there was a parameter passed for a specific EDP-IDF directory :: this may be different than the standard ESP-IDF environment (e.g. VisualGDB) -if not "%1" == "" ( - if not exist "%1" ( +if not "%Arg1%" == "" ( +echo %Arg1% + if not exist "%Arg1%" ( echo "ERROR: optional directory was specified, but not found: %1" goto :ERR ) - - SET IDF_PATH=%1 + echo "Setting IDF path" + SET IDF_PATH=%Arg1% echo Using specified IDF_PATH: %IDF_PATH% ) @@ -69,14 +73,14 @@ echo Using WOLFSSLEXP_TRG_DIR = %WOLFSSLEXP_TRG_DIR% echo; echo Equivalalent destination path: -dir %WOLFSSL_ESPIDFDIR%\*.xyzzy 2> nul | findstr \ +dir "%WOLFSSL_ESPIDFDIR%\*.xyzzy" 2> nul | findstr \ echo; echo Equivalalent source directory paths: :: show the path of the equivalent %VALUE% (search for files that don't exist, supress error, and look for string with "\") -dir %BASEDIR%\*.xyzzy 2> nul | findstr \ -dir %WOLFSSLLIB_TRG_DIR%\*.xyzzy 2> nul | findstr \ -dir %WOLFSSLEXP_TRG_DIR%\*.xyzzy 2> nul | findstr \ +dir "%BASEDIR%\*.xyzzy" 2> nul | findstr \ +dir "%WOLFSSLLIB_TRG_DIR%\*.xyzzy" 2> nul | findstr \ +dir "%WOLFSSLEXP_TRG_DIR%\*.xyzzy" 2> nul | findstr \ :: set the FileStamp variable to the current date: YYMMYY_HHMMSS :: the simplest method, to use existing TIME ad DATE variables: @@ -92,18 +96,18 @@ if "%TIME:~0,1%" == " " set FileStamp=%DATE:~12,2%%DATE:~7,2%%DATE:~4,2%_0% if NOT "%TIME:~0,1%" == " " set FileStamp=%DATE:~12,2%%DATE:~7,2%%DATE:~4,2%_%TIME:~0,2%%TIME:~3,2%%TIME:~6,2% :: Backup existing user settings -if exist %WOLFSSLLIB_TRG_DIR%\include\config.h ( +if exist "%WOLFSSLLIB_TRG_DIR%\include\config.h" ( echo; echo Saving: %WOLFSSLLIB_TRG_DIR%\include\config.h echo to: %SCRIPTDIR%\config_h_%FileStamp%.bak - copy %WOLFSSLLIB_TRG_DIR%\include\config.h %SCRIPTDIR%\config_h_%FileStamp%.bak + copy "%WOLFSSLLIB_TRG_DIR%\include\config.h" "%SCRIPTDIR%\config_h_%FileStamp%.bak" echo; ) -if exist %WOLFSSL_ESPIDFDIR%\user_settings.h ( +if exist "%WOLFSSL_ESPIDFDIR%\user_settings.h" ( echo Saving: %WOLFSSLLIB_TRG_DIR%\include\user_settings.h echo to: %SCRIPTDIR%\user_settings_h_%FileStamp%.bak - copy %WOLFSSLLIB_TRG_DIR%\include\user_settings.h %SCRIPTDIR%\user_settings_h_%FileStamp%.bak + copy "%WOLFSSLLIB_TRG_DIR%\include\user_settings.h" "%SCRIPTDIR%\user_settings_h_%FileStamp%.bak" echo; ) @@ -111,7 +115,7 @@ if exist %WOLFSSL_ESPIDFDIR%\user_settings.h ( ::****************************************************************************************************** :: check if there's already an existing %WOLFSSLLIB_TRG_DIR% and confirm removal ::****************************************************************************************************** -if exist %WOLFSSLLIB_TRG_DIR% ( +if exist "%WOLFSSLLIB_TRG_DIR%" ( echo; echo WARNING: Existing files found in %WOLFSSLLIB_TRG_DIR% echo; @@ -144,11 +148,11 @@ if exist %WOLFSSLLIB_TRG_DIR% ( ::****************************************************************************************************** :: purge existing directory -if exist %WOLFSSLLIB_TRG_DIR% ( +if exist "%WOLFSSLLIB_TRG_DIR%" ( echo; echo Removing %WOLFSSLLIB_TRG_DIR% - rmdir %WOLFSSLLIB_TRG_DIR% /S /Q - if exist %WOLFSSLLIB_TRG_DIR% ( + rmdir "%WOLFSSLLIB_TRG_DIR%" /S /Q + if exist "%WOLFSSLLIB_TRG_DIR%" ( SET COPYERROR=true echo; echo WARNING: Failed to remove %WOLFSSLLIB_TRG_DIR% @@ -166,67 +170,67 @@ if exist %WOLFSSLLIB_TRG_DIR% ( ::****************************************************************************************************** :REFRESH ::****************************************************************************************************** -if not exist %WOLFSSLLIB_TRG_DIR% mkdir %WOLFSSLLIB_TRG_DIR% -if not exist %WOLFSSLLIB_TRG_DIR%\src mkdir %WOLFSSLLIB_TRG_DIR%\src -if not exist %WOLFSSLLIB_TRG_DIR%\wolfcrypt\src mkdir %WOLFSSLLIB_TRG_DIR%\wolfcrypt\src -if not exist %WOLFSSLLIB_TRG_DIR%\wolfssl mkdir %WOLFSSLLIB_TRG_DIR%\wolfssl -if not exist %WOLFSSLLIB_TRG_DIR%\wolfssl\openssl mkdir %WOLFSSLLIB_TRG_DIR%\wolfssl\openssl -if not exist %WOLFSSLLIB_TRG_DIR%\test mkdir %WOLFSSLLIB_TRG_DIR%\test -if not exist %WOLFSSLLIB_TRG_DIR%\include mkdir %WOLFSSLLIB_TRG_DIR%\include +if not exist "%WOLFSSLLIB_TRG_DIR%" mkdir "%WOLFSSLLIB_TRG_DIR%" +if not exist "%WOLFSSLLIB_TRG_DIR%\src" mkdir "%WOLFSSLLIB_TRG_DIR%\src" +if not exist "%WOLFSSLLIB_TRG_DIR%\wolfcrypt\src" mkdir "%WOLFSSLLIB_TRG_DIR%\wolfcrypt\src" +if not exist "%WOLFSSLLIB_TRG_DIR%\wolfssl" mkdir "%WOLFSSLLIB_TRG_DIR%\wolfssl" +if not exist "%WOLFSSLLIB_TRG_DIR%\wolfssl\openssl" mkdir "%WOLFSSLLIB_TRG_DIR%\wolfssl\openssl" +if not exist "%WOLFSSLLIB_TRG_DIR%\test" mkdir "%WOLFSSLLIB_TRG_DIR%\test"" +if not exist "%WOLFSSLLIB_TRG_DIR%\include" mkdir "%WOLFSSLLIB_TRG_DIR%\include" rem copying ... files in src/ into $WOLFSSLLIB_TRG_DIR%/src echo; echo Copying files to %WOLFSSLLIB_TRG_DIR%\src\ -xcopy %BASEDIR%\src\*.c %WOLFSSLLIB_TRG_DIR%\src\ /S /E /Q /Y +xcopy "%BASEDIR%\src\*.c" "%WOLFSSLLIB_TRG_DIR%\src\" /S /E /Q /Y if %errorlevel% NEQ 0 SET COPYERROR=true echo; echo Copying src\*.c files to %WOLFSSLLIB_TRG_DIR%\wolfcrypt\src -xcopy %BASEDIR%\wolfcrypt\src\*.c %WOLFSSLLIB_TRG_DIR%\wolfcrypt\src /S /E /Q /Y +xcopy "%BASEDIR%\wolfcrypt\src\*.c" "%WOLFSSLLIB_TRG_DIR%\wolfcrypt\src" /S /E /Q /Y if %errorlevel% NEQ 0 SET COPYERROR=true echo; echo Copying src\*.i files to %WOLFSSLLIB_TRG_DIR%\wolfcrypt\src -xcopy %BASEDIR%\wolfcrypt\src\*.i %WOLFSSLLIB_TRG_DIR%\wolfcrypt\src /S /E /Q /Y +xcopy "%BASEDIR%\wolfcrypt\src\*.i" "%WOLFSSLLIB_TRG_DIR%\wolfcrypt\src" /S /E /Q /Y if %errorlevel% NEQ 0 SET COPYERROR=true echo; echo Copying files to %WOLFSSLLIB_TRG_DIR%\wolfcrypt\src\port\ -xcopy %BASEDIR%\wolfcrypt\src\port %WOLFSSLLIB_TRG_DIR%\wolfcrypt\src\port\ /S /E /Q /Y +xcopy "%BASEDIR%\wolfcrypt\src\port" "%WOLFSSLLIB_TRG_DIR%\wolfcrypt\src\port\" /S /E /Q /Y if %errorlevel% NEQ 0 SET COPYERROR=true echo; echo Copying files to %WOLFSSLLIB_TRG_DIR%\wolfcrypt\test\ -xcopy %BASEDIR%\wolfcrypt\test %WOLFSSLLIB_TRG_DIR%\wolfcrypt\test\ /S /E /Q /Y +xcopy "%BASEDIR%\wolfcrypt\test" "%WOLFSSLLIB_TRG_DIR%\wolfcrypt\test\" /S /E /Q /Y if %errorlevel% NEQ 0 SET COPYERROR=true :: Copy dummy test_paths.h to handle the case configure hasn't yet executed echo; echo Copying dummy_test_paths.h to %WOLFSSLLIB_TRG_DIR%\wolfcrypt\test\test_paths.h -echo new config > %WOLFSSLLIB_TRG_DIR%\wolfcrypt\test\test_paths.h +echo new config > "%WOLFSSLLIB_TRG_DIR%\wolfcrypt\test\test_paths.h" if %errorlevel% NEQ 0 SET COPYERROR=true -xcopy %WOLFSSL_ESPIDFDIR%\dummy_test_paths.h %WOLFSSLLIB_TRG_DIR%\wolfcrypt\test\test_paths.h /S /E /Y +xcopy "%WOLFSSL_ESPIDFDIR%\dummy_test_paths.h" "%WOLFSSLLIB_TRG_DIR%\wolfcrypt\test\test_paths.h" /S /E /Y if %errorlevel% NEQ 0 SET COPYERROR=true echo; echo Copying files to %WOLFSSLLIB_TRG_DIR%\wolfcrypt\benchmark\ -xcopy %BASEDIR%\wolfcrypt\benchmark %WOLFSSLLIB_TRG_DIR%\wolfcrypt\benchmark\ /S /E /Q /Y +xcopy "%BASEDIR%\wolfcrypt\benchmark" "%WOLFSSLLIB_TRG_DIR%\wolfcrypt\benchmark\" /S /E /Q /Y if %errorlevel% NEQ 0 SET COPYERROR=true echo; echo Copying files to %WOLFSSLLIB_TRG_DIR%\wolfssl\ -xcopy %BASEDIR%\wolfssl\*.h %WOLFSSLLIB_TRG_DIR%\wolfssl\ /S /E /Q /Y +xcopy "%BASEDIR%\wolfssl\*.h" "%WOLFSSLLIB_TRG_DIR%\wolfssl\" /S /E /Q /Y if %errorlevel% NEQ 0 SET COPYERROR=true echo; echo Copying files to%WOLFSSLLIB_TRG_DIR%\wolfssl\openssl\ -xcopy %BASEDIR%\wolfssl\openssl\*.h %WOLFSSLLIB_TRG_DIR%\wolfssl\openssl\ /S /E /Q /Y +xcopy "%BASEDIR%\wolfssl\openssl\*.h" "%WOLFSSLLIB_TRG_DIR%\wolfssl\openssl\" /S /E /Q /Y if %errorlevel% NEQ 0 SET COPYERROR=true echo; echo Copying files to %WOLFSSLLIB_TRG_DIR%\wolfssl\wolfcrypt\ -xcopy %BASEDIR%\wolfssl\wolfcrypt %WOLFSSLLIB_TRG_DIR%\wolfssl\wolfcrypt\ /S /E /Q /Y +xcopy "%BASEDIR%\wolfssl\wolfcrypt" "%WOLFSSLLIB_TRG_DIR%\wolfssl\wolfcrypt\" /S /E /Q /Y if %errorlevel% NEQ 0 SET COPYERROR=true @@ -236,15 +240,15 @@ if %errorlevel% NEQ 0 SET COPYERROR=true :: user_settings.h (default, may be overwritten by prior file) echo; echo Copying default user_settings.h to %WOLFSSLLIB_TRG_DIR%\include\ -xcopy %WOLFSSL_ESPIDFDIR%\user_settings.h %WOLFSSLLIB_TRG_DIR%\include\ /F +xcopy "%WOLFSSL_ESPIDFDIR%\user_settings.h" "%WOLFSSLLIB_TRG_DIR%\include\" /F if %errorlevel% NEQ 0 SET COPYERROR=true :: echo Creating new config file: %WOLFSSLLIB_TRG_DIR%\include\config.h (default, may be overwritten by prior file) -echo new config > %WOLFSSLLIB_TRG_DIR%\include\config.h -xcopy %WOLFSSL_ESPIDFDIR%\dummy_config_h. %WOLFSSLLIB_TRG_DIR%\include\config.h /F /Y +:: using copy instead of copy to avoid file/directory prompt for files without extension +echo new config > "%WOLFSSLLIB_TRG_DIR%\include\config.h" +xcopy "%WOLFSSL_ESPIDFDIR%\dummy_config_h" "%WOLFSSLLIB_TRG_DIR%\include\config.h" /F /Y if %errorlevel% NEQ 0 SET COPYERROR=true - :: Check if operator wants to keep prior config.h if EXIST config_h_%FileStamp%.bak ( echo; @@ -252,7 +256,7 @@ if EXIST config_h_%FileStamp%.bak ( call; choice /c YN /m "Use your prior config.h " if errorlevel 2 GOTO :NO_CONFIG_RESTORE - xcopy config_h_%FileStamp%.bak %WOLFSSLLIB_TRG_DIR%\include\config.h /Y + xcopy "config_h_%FileStamp%.bak" "%WOLFSSLLIB_TRG_DIR%\include\config.h" /Y if %errorlevel% NEQ 0 SET COPYERROR=true ) else ( @@ -270,7 +274,7 @@ if EXIST user_settings_h_%FileStamp%.bak ( call; choice /c YN /m "User your prior user_settings.h " if errorlevel 2 GOTO :NO_USER_SETTINGS_RESTORE - xcopy user_settings_h_%FileStamp%.bak %WOLFSSLLIB_TRG_DIR%\include\user_settings.h /Y + xcopy user_settings_h_%FileStamp%.bak "%WOLFSSLLIB_TRG_DIR%\include\user_settings.h" /Y if %errorlevel% NEQ 0 SET COPYERROR=true ) else ( @@ -286,63 +290,63 @@ if EXIST user_settings_h_%FileStamp%.bak ( :: unit test app echo; echo Copying unit files to %WOLFSSLLIB_TRG_DIR%\test\ -xcopy %WOLFSSL_ESPIDFDIR%\test %WOLFSSLLIB_TRG_DIR%\test\ /S /E /Q /Y +xcopy "%WOLFSSL_ESPIDFDIR%\test" "%WOLFSSLLIB_TRG_DIR%\test\" /S /E /Q /Y if %errorlevel% NEQ 0 GOTO :COPYERR echo; echo Copying CMakeLists.txt to %WOLFSSLLIB_TRG_DIR%\ -xcopy %WOLFSSL_ESPIDFDIR%\libs\CMakeLists.txt %WOLFSSLLIB_TRG_DIR%\ /F +xcopy "%WOLFSSL_ESPIDFDIR%\libs\CMakeLists.txt" "%WOLFSSLLIB_TRG_DIR%\" /F if %errorlevel% NEQ 0 GOTO :COPYERR echo; echo Copying component.mk to %WOLFSSLLIB_TRG_DIR%\ -xcopy %WOLFSSL_ESPIDFDIR%\libs\component.mk %WOLFSSLLIB_TRG_DIR%\ /F +xcopy "%WOLFSSL_ESPIDFDIR%\libs\component.mk" "%WOLFSSLLIB_TRG_DIR%\" /F if %errorlevel% NEQ 0 GOTO :COPYERR :: Benchmark program echo; echo Removing %WOLFSSLEXP_TRG_DIR%\wolfssl_benchmark\ -rmdir %WOLFSSLEXP_TRG_DIR%\wolfssl_benchmark\ /S /Q +rmdir "%WOLFSSLEXP_TRG_DIR%\wolfssl_benchmark\" /S /Q if %errorlevel% NEQ 0 GOTO :COPYERR echo; echo Copying %WOLFSSLEXP_TRG_DIR%\wolfssl_benchmark\main\ -mkdir %WOLFSSLEXP_TRG_DIR%\wolfssl_benchmark\main\ +mkdir "%WOLFSSLEXP_TRG_DIR%\wolfssl_benchmark\main\" -xcopy %BASEDIR%\wolfcrypt\benchmark\benchmark.c %WOLFSSLEXP_TRG_DIR%\wolfssl_benchmark\main\ /F /Y +xcopy "%BASEDIR%\wolfcrypt\benchmark\benchmark.c" "%WOLFSSLEXP_TRG_DIR%\wolfssl_benchmark\main\" /F /Y if %errorlevel% NEQ 0 GOTO :COPYERR -xcopy %WOLFSSL_ESPIDFDIR%\examples\wolfssl_benchmark %WOLFSSLEXP_TRG_DIR%\wolfssl_benchmark\ /Q /Y +xcopy "%WOLFSSL_ESPIDFDIR%\examples\wolfssl_benchmark" "%WOLFSSLEXP_TRG_DIR%\wolfssl_benchmark\" /Q /Y if %errorlevel% NEQ 0 GOTO :COPYERR :: Crypt Test program echo; echo Copying %WOLFSSLEXP_TRG_DIR%\wolfssl_test\ -rmdir %WOLFSSLEXP_TRG_DIR%\wolfssl_test\ /S /Q -mkdir %WOLFSSLEXP_TRG_DIR%\wolfssl_test\main\ +rmdir "%WOLFSSLEXP_TRG_DIR%\wolfssl_test\" /S /Q +mkdir "%WOLFSSLEXP_TRG_DIR%\wolfssl_test\main\" -xcopy %BASEDIR%\wolfcrypt\test\test.c %WOLFSSLEXP_TRG_DIR%\wolfssl_test\main\ /S /E /Q /Y +xcopy "%BASEDIR%\wolfcrypt\test\test.c" "%WOLFSSLEXP_TRG_DIR%\wolfssl_test\main\" /S /E /Q /Y if %errorlevel% NEQ 0 GOTO :COPYERR -xcopy %WOLFSSL_ESPIDFDIR%\examples\wolfssl_test %WOLFSSLEXP_TRG_DIR%\wolfssl_test\ /S /E /Q /Y +xcopy "%WOLFSSL_ESPIDFDIR%\examples\wolfssl_test" "%WOLFSSLEXP_TRG_DIR%\wolfssl_test\" /S /E /Q /Y if %errorlevel% NEQ 0 GOTO :COPYERR :: TLS Client program echo; echo Copying %WOLFSSLEXP_TRG_DIR%\wolfssl_client\ -rmdir %WOLFSSLEXP_TRG_DIR%\wolfssl_client\ /S /Q -mkdir %WOLFSSLEXP_TRG_DIR%\wolfssl_client\main\ +rmdir "%WOLFSSLEXP_TRG_DIR%\wolfssl_client\" /S /Q +mkdir "%WOLFSSLEXP_TRG_DIR%\wolfssl_client\main\" -xcopy %WOLFSSL_ESPIDFDIR%\examples\wolfssl_client %WOLFSSLEXP_TRG_DIR%\wolfssl_client\ /S /E /Q /Y +xcopy "%WOLFSSL_ESPIDFDIR%\examples\wolfssl_client" "%WOLFSSLEXP_TRG_DIR%\wolfssl_client\" /S /E /Q /Y if %errorlevel% NEQ 0 GOTO :COPYERR :: TLS Server program echo; echo Copying %WOLFSSLEXP_TRG_DIR%\wolfssl_server\ -rmdir %WOLFSSLEXP_TRG_DIR%\wolfssl_server\ /S /Q -mkdir %WOLFSSLEXP_TRG_DIR%\wolfssl_server\main\ +rmdir "%WOLFSSLEXP_TRG_DIR%\wolfssl_server\" /S /Q +mkdir "%WOLFSSLEXP_TRG_DIR%\wolfssl_server\main\" -xcopy %WOLFSSL_ESPIDFDIR%\examples\wolfssl_server %WOLFSSLEXP_TRG_DIR%\wolfssl_server\ /S /E /Q /Y +xcopy "%WOLFSSL_ESPIDFDIR%\examples\wolfssl_server" "%WOLFSSLEXP_TRG_DIR%\wolfssl_server\" /S /E /Q /Y if %errorlevel% NEQ 0 GOTO :COPYERR goto :DONE @@ -369,6 +373,7 @@ goto :ERR ::****************************************************************************************************** :ERR ::****************************************************************************************************** +echo "ERROR" exit /B 1 :: Success diff --git a/IDE/Espressif/ESP-IDF/user_settings.h b/IDE/Espressif/ESP-IDF/user_settings.h index 215b37690b..6a37e2a923 100644 --- a/IDE/Espressif/ESP-IDF/user_settings.h +++ b/IDE/Espressif/ESP-IDF/user_settings.h @@ -38,6 +38,18 @@ /* #define DEBUG_WOLFSSL_VERBOSE */ +/* Enable key generation: +https://www.wolfssl.com/documentation/manuals/wolfssl/chapter07.html#rsa-key-generation */ +#define WOLFSSL_KEY_GEN + +/* Enable certificate generation: +https://www.wolfssl.com/documentation/manuals/wolfssl/chapter07.html#certificate-generation */ +#define WOLFSSL_CERT_GEN + +/* Enable certificate request generation: +https://www.wolfssl.com/documentation/manuals/wolfssl/chapter07.html#certificate-signing-request-csr-generation */ +#define WOLFSSL_CERT_REQ + #define BENCH_EMBEDDED #define USE_CERT_BUFFERS_2048 @@ -54,13 +66,36 @@ #define NO_FILESYSTEM #define HAVE_AESGCM -/* when you want to use SHA384 */ + +/* +Enable SHA-384 support +See: https://www.wolfssl.com/documentation/manuals/wolfssl/chapter02.html#wolfssl_sha384 +Note: currently not working. See https://github.com/gojimmypi/wolfssl/tree/ED25519_SHA2_fix/ */ /* #define WOLFSSL_SHA384 */ + + #define WOLFSSL_SHA512 #define HAVE_ECC #define HAVE_CURVE25519 #define CURVE25519_SMALL -#define HAVE_ED25519 + +// ED25519 test fails on ESP32 & ESP32s3 +/* Enable ES25519 support. +Currently failing for ESP32 & ESP32s3. +See: https://github.com/wolfSSL/wolfssl/issues/5948 +and: https://github.com/gojimmypi/wolfssl/tree/ED25519_SHA2_fix/ */ +/* #define HAVE_ED25519 */ + +/* Disable SHA-512/224 & SHA-512/256; currently not working. +See https://github.com/gojimmypi/wolfssl/tree/ED25519_SHA2_fix/ */ +#define WOLFSSL_NOSHA512_224 +#define WOLFSSL_NOSHA512_256 + +/* AES-192 is not supported on the ESP32s3; is available for ESP32 + * and may be available for other devices. */ +#if !defined(CONFIG_IDF_TARGET_ESP32S3) +#define NO_AES_192 +#endif /* when you want to use pkcs7 */ /* #define HAVE_PKCS7 */ @@ -98,9 +133,13 @@ /* debug options */ /* #define DEBUG_WOLFSSL */ -/* #define WOLFSSL_ESP32WROOM32_CRYPT_DEBUG */ /* #define WOLFSSL_ATECC508A_DEBUG */ +/* Note: WOLFSSL_ESP32WROOM32_CRYPT_DEBUG not available for ESP32s3 due +to issue including "esp_timer.h". See https://github.com/gojimmypi/wolfssl/tree/ED25519_SHA2_fix/ +for pending solution. */ +/* #define WOLFSSL_ESP32WROOM32_CRYPT_DEBUG */ + /* date/time */ /* if it cannot adjust time in the device, */ /* enable macro below */ diff --git a/wolfcrypt/src/aes.c b/wolfcrypt/src/aes.c index 63928bafea..58163e2869 100644 --- a/wolfcrypt/src/aes.c +++ b/wolfcrypt/src/aes.c @@ -2676,6 +2676,23 @@ static WARN_UNUSED_RESULT int wc_AesDecrypt( return BAD_FUNC_ARG; } +#if !defined(WOLFSSL_AES_128) + if (keylen == 16) { + return BAD_FUNC_ARG; + } +#endif + +#if !defined(WOLFSSL_AES_192) + if (keylen == 24) { + return BAD_FUNC_ARG; + } +#endif +#if !defined(WOLFSSL_AES_256) + if (keylen == 32) { + return BAD_FUNC_ARG; + } +#endif + aes->keylen = keylen; aes->rounds = keylen/4 + 6; diff --git a/wolfcrypt/src/port/Espressif/README.md b/wolfcrypt/src/port/Espressif/README.md index fe98e3be65..d57bbc654f 100644 --- a/wolfcrypt/src/port/Espressif/README.md +++ b/wolfcrypt/src/port/Espressif/README.md @@ -1,6 +1,9 @@ # ESP32 Port Support for the ESP32-WROOM-32 on-board crypto hardware acceleration for symmetric AES, SHA1/SHA256/SHA384/SHA512 and RSA primitive including mul, mulmod and exptmod. +Supported hardware includes: +* ESP32 +* ESP32s3 ## ESP32 Acceleration diff --git a/wolfcrypt/src/port/Espressif/esp32_aes.c b/wolfcrypt/src/port/Espressif/esp32_aes.c index 0603f169e5..51129b1ab0 100644 --- a/wolfcrypt/src/port/Espressif/esp32_aes.c +++ b/wolfcrypt/src/port/Espressif/esp32_aes.c @@ -38,7 +38,8 @@ #include #include "wolfssl/wolfcrypt/port/Espressif/esp32-crypt.h" - +#include + static const char* TAG = "wolf_hw_aes"; /* mutex */ @@ -84,6 +85,13 @@ static int esp_aes_hw_InUse() /* Enable AES hardware */ periph_module_enable(PERIPH_AES_MODULE); + +#if CONFIG_IDF_TARGET_ESP32S3 + /* Select working mode. Can be typical or DMA. + * 0 => typical + * 1 => DMA */ + DPORT_REG_WRITE(AES_DMA_ENABLE_REG, 0); +#endif ESP_LOGV(TAG, "leave esp_aes_hw_InUse"); return ret; @@ -106,8 +114,9 @@ static void esp_aes_hw_Leave( void ) /* * set key to hardware key registers. + * return 0 on success; -1 if mode isn't supported. */ -static void esp_aes_hw_Set_KeyMode(Aes *ctx, ESP32_AESPROCESS mode) +static int esp_aes_hw_Set_KeyMode(Aes *ctx, ESP32_AESPROCESS mode) { word32 i; word32 mode_ = 0; @@ -124,7 +133,7 @@ static void esp_aes_hw_Set_KeyMode(Aes *ctx, ESP32_AESPROCESS mode) } else { ESP_LOGE(TAG, " >> unexpected error."); - return; + return -1; } } @@ -133,26 +142,39 @@ static void esp_aes_hw_Set_KeyMode(Aes *ctx, ESP32_AESPROCESS mode) DPORT_REG_WRITE(AES_KEY_BASE + (i*4), *(((word32*)ctx->key) + i)); } - /* mode - * 0 AES-128 Encryption - * 1 AES-192 Encryption - * 2 AES-256 Encryption - * 4 AES-128 Decryption - * 5 AES-192 Decryption - * 6 AES-256 Decryption + /* + * ESP32: see table 22-1 in ESP32 Technical Reference + * ESP32S3: see table 19-2 in ESP32S3 Technical Reference + * mode Algorithm ESP32 ESP32S3 + * 0 AES-128 Encryption y y + * 1 AES-192 Encryption y n + * 2 AES-256 Encryption y y + * 4 AES-128 Decryption y y + * 5 AES-192 Decryption y n + * 6 AES-256 Decryption y y */ switch(ctx->keylen){ case 24: mode_ += 1; break; case 32: mode_ += 2; break; default: break; } - +#if CONFIG_IDF_TARGET_ESP32S3 + if (mode_ == 1 || mode_ == 5 || mode_ == 7) + { + ESP_LOGE(TAG, " unsupported mode"); + return -1; + } +#endif DPORT_REG_WRITE(AES_MODE_REG, mode_); ESP_LOGV(TAG, " leave esp_aes_hw_Setkey"); + + return 0; } /* * Process a one block of AES + * in: block of 16 bytes (4 x words32) to process + * out: result of processing input bytes. */ static void esp_aes_bk(const byte* in, byte* out) { @@ -164,7 +186,27 @@ static void esp_aes_bk(const byte* in, byte* out) #endif ESP_LOGV(TAG, "enter esp_aes_bk"); +#if CONFIG_IDF_TARGET_ESP32S3 + // See esp32-s3 technical reference manual §19.4.3 Operation process + // using CPU working mode. The ESP32-S3 also supports a DMA mode. + /* copy text for encrypting/decrypting blocks */ + DPORT_REG_WRITE(AES_TEXT_IN_BASE, inwords[0]); + DPORT_REG_WRITE(AES_TEXT_IN_BASE + 4, inwords[1]); + DPORT_REG_WRITE(AES_TEXT_IN_BASE + 8, inwords[2]); + DPORT_REG_WRITE(AES_TEXT_IN_BASE + 12, inwords[3]); + /* start engine */ + DPORT_REG_WRITE(AES_TRIGGER_REG, 1); + + /* wait until finishing the process */ + while (DPORT_REG_READ(AES_STATE_REG) != 0) + { + // wating for the hardware accelerator to complete operation. + } + + /* read-out blocks */ + esp_dport_access_read_buffer(outwords, AES_TEXT_OUT_BASE, 4); +#else /* copy text for encrypting/decrypting blocks */ DPORT_REG_WRITE(AES_TEXT_BASE, inwords[0]); DPORT_REG_WRITE(AES_TEXT_BASE + 4, inwords[1]); @@ -182,6 +224,8 @@ static void esp_aes_bk(const byte* in, byte* out) /* read-out blocks */ esp_dport_access_read_buffer(outwords, AES_TEXT_BASE, 4); +#endif + ESP_LOGV(TAG, "leave esp_aes_bk"); } @@ -192,6 +236,7 @@ static void esp_aes_bk(const byte* in, byte* out) * @param in : a pointer of the input buffer containing plain text to be encrypted * @param out: a pointer of the output buffer in which to store the cipher text of * the encrypted message +* @return: 0 on success, BAD_FUNC_ARG if the AES algorithm isn't supported. */ int wc_esp32AesEncrypt(Aes *aes, const byte* in, byte* out) { @@ -199,7 +244,12 @@ int wc_esp32AesEncrypt(Aes *aes, const byte* in, byte* out) /* lock the hw engine */ esp_aes_hw_InUse(); /* load the key into the register */ - esp_aes_hw_Set_KeyMode(aes, ESP32_AES_UPDATEKEY_ENCRYPT); + if (0 != esp_aes_hw_Set_KeyMode(aes, ESP32_AES_UPDATEKEY_ENCRYPT)) + { + /* release hw */ + esp_aes_hw_Leave(); + return BAD_FUNC_ARG; + } /* process a one block of AES */ esp_aes_bk(in, out); /* release hw */ @@ -214,6 +264,7 @@ int wc_esp32AesEncrypt(Aes *aes, const byte* in, byte* out) * @param in : a pointer of the input buffer containing plain text to be decrypted * @param out: a pointer of the output buffer in which to store the cipher text of * the decrypted message +* @return: 0 on success, BAD_FUNC_ARG if the AES algorithm isn't supported. */ int wc_esp32AesDecrypt(Aes *aes, const byte* in, byte* out) { @@ -221,7 +272,12 @@ int wc_esp32AesDecrypt(Aes *aes, const byte* in, byte* out) /* lock the hw engine */ esp_aes_hw_InUse(); /* load the key into the register */ - esp_aes_hw_Set_KeyMode(aes, ESP32_AES_UPDATEKEY_DECRYPT); + if (0 != esp_aes_hw_Set_KeyMode(aes, ESP32_AES_UPDATEKEY_DECRYPT)) + { + /* release hw */ + esp_aes_hw_Leave(); + return BAD_FUNC_ARG; + } /* process a one block of AES */ esp_aes_bk(in, out); /* release hw engine */ @@ -239,6 +295,7 @@ int wc_esp32AesDecrypt(Aes *aes, const byte* in, byte* out) * the encrypted message * @param in : a pointer of the input buffer containing plain text to be encrypted * @param sz : size of input message +* @return: 0 on success, BAD_FUNC_ARG if the AES algorithm isn't supported. */ int wc_esp32AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) { @@ -254,7 +311,12 @@ int wc_esp32AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) esp_aes_hw_InUse(); - esp_aes_hw_Set_KeyMode(aes, ESP32_AES_UPDATEKEY_ENCRYPT); + if (0 != esp_aes_hw_Set_KeyMode(aes, ESP32_AES_UPDATEKEY_ENCRYPT)) + { + /* release hw */ + esp_aes_hw_Leave(); + return BAD_FUNC_ARG; + } while (blocks--) { XMEMCPY(temp_block, in + offset, AES_BLOCK_SIZE); @@ -285,6 +347,7 @@ int wc_esp32AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) * the decrypted message * @param in : a pointer of the input buffer containing plain text to be decrypted * @param sz : size of input message +* @return: 0 on success, BAD_FUNC_ARG if the AES algorithm isn't supported. */ int wc_esp32AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) { @@ -300,7 +363,12 @@ int wc_esp32AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) esp_aes_hw_InUse(); - esp_aes_hw_Set_KeyMode(aes, ESP32_AES_UPDATEKEY_DECRYPT); + if (0 != esp_aes_hw_Set_KeyMode(aes, ESP32_AES_UPDATEKEY_DECRYPT)) + { + /* release hw */ + esp_aes_hw_Leave(); + return BAD_FUNC_ARG; + } while (blocks--) { XMEMCPY(temp_block, in + offset, AES_BLOCK_SIZE); diff --git a/wolfcrypt/src/port/Espressif/esp32_mp.c b/wolfcrypt/src/port/Espressif/esp32_mp.c index 2e16be89b3..1b40f4e813 100644 --- a/wolfcrypt/src/port/Espressif/esp32_mp.c +++ b/wolfcrypt/src/port/Espressif/esp32_mp.c @@ -48,6 +48,7 @@ static const char* const TAG = "wolfssl_mp"; #define ESP_HW_RSAMIN_BIT 512 #define BYTE_TO_WORDS(s) (((s+3)>>2)) /* (s+(4-1))/ 4 */ #define BITS_TO_WORDS(s) (((s+31)>>3)>>2) /* (s+(32-1))/ 8/ 4*/ +#define BITS_IN_ONE_WORD 32 #define MP_NG -1 @@ -70,10 +71,20 @@ static int esp_mp_hw_wait_clean() { word32 timeout = 0; +#if CONFIG_IDF_TARGET_ESP32S3 + + while (!ESP_TIMEOUT(++timeout) && DPORT_REG_READ(RSA_QUERY_CLEAN_REG) != 1) + { + /* wait. expected delay 1 to 2 uS */ + } +#else + /* RSA_CLEAN_REG is now called RSA_QUERY_CLEAN_REG. hwcrypto_reg.h maintains + * RSA_CLEAN_REG for backwards compatibility so this block _might_ be not needed. */ while(!ESP_TIMEOUT(++timeout) && DPORT_REG_READ(RSA_CLEAN_REG) != 1) { /* wait. expected delay 1 to 2 uS */ } +#endif if (ESP_TIMEOUT(timeout)) { ESP_LOGE(TAG, "waiting hw ready is timed out."); @@ -131,12 +142,22 @@ static int esp_mp_hw_lock() return MP_NG; } + +#if CONFIG_IDF_TARGET_ESP32S3 + /* Activate teh 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? */ + periph_module_enable(PERIPH_RSA_MODULE); + + /* clear bit to enable hardware operation; (set to disable) */ + DPORT_REG_CLR_BIT(SYSTEM_RSA_PD_CTRL_REG, SYSTEM_RSA_MEM_PD); +#else /* Enable RSA hardware */ periph_module_enable(PERIPH_RSA_MODULE); - /* clear bit to enable hardware operation; (set to disable) - */ + /* clear bit to enable hardware operation; (set to disable) */ DPORT_REG_CLR_BIT(DPORT_RSA_PD_CTRL_REG, DPORT_RSA_PD); +#endif /* remionder: wait until RSA_CLEAN_REG reads 1 * see esp_mp_hw_wait_clean() @@ -150,13 +171,22 @@ static int esp_mp_hw_lock() */ static void esp_mp_hw_unlock( void ) { +#if CONFIG_IDF_TARGET_ESP32S3 + /* Deactivate teh RSA accelerator. See §20.3 of ESP32-S3 technical manual. + * periph_module_enable doesn't seem to be documented and in private folder + * with v5 release. Maybe it will be deprecated? */ + DPORT_REG_SET_BIT(SYSTEM_RSA_PD_CTRL_REG, SYSTEM_RSA_MEM_PD); + periph_module_disable(PERIPH_RSA_MODULE); + +#else /* set bit to disabled hardware operation; (clear to enable) */ DPORT_REG_SET_BIT(DPORT_RSA_PD_CTRL_REG, DPORT_RSA_PD); /* Disable RSA hardware */ periph_module_disable(PERIPH_RSA_MODULE); - +#endif + /* unlock */ esp_CryptHwMutexUnLock(&mp_mutex); } @@ -199,7 +229,7 @@ static void process_start(word32 reg) } /* wait until done */ -static int wait_uitil_done(word32 reg) +static int wait_until_done(word32 reg) { word32 timeout = 0; /* wait until done && not timeout */ @@ -210,7 +240,7 @@ static int wait_uitil_done(word32 reg) /* clear interrupt */ DPORT_REG_WRITE(RSA_INTERRUPT_REG, 1); - + if (ESP_TIMEOUT(timeout)) { ESP_LOGE(TAG, "rsa operation is timed out."); return MP_NG; @@ -295,7 +325,83 @@ int esp_mp_mul(fp_int* X, fp_int* Y, fp_int* Z) { int ret = 0; int neg = (X->sign == Y->sign)? MP_ZPOS : MP_NEG; + +#if CONFIG_IDF_TARGET_ESP32S3 + + int nBitsInX = mp_count_bits(X); + int nBitsInY = mp_count_bits(Y); + + /* X & Y must be represented by the same number of bits. Must be + * enough to represent the larger one. */ + int nMinXYBits = max(nBitsInX, nBitsInY); + + /* Figure out how many words we need to represent each operand & the result. */ + int nWordsForOperand = bits2words(nMinXYBits); + int nWordsForResult = bits2words(nBitsInX + nBitsInY); + + /* Make sure we are within capabilities of hardware. */ + if ((nWordsForOperand * BITS_IN_ONE_WORD) > ESP_HW_MULTI_RSAMAX_BITS) { + ESP_LOGW(TAG, "exceeds max bit length(2048)"); + return -2; + } + + /* Steps to perform large number multiplication. Calculates Z = X x Y. The number of + * bits in the operands (X, Y) is N. N can be 32x, where x = {1,2,3,...64}, so the + * maximum number of bits in the X and Y is 2048. + * See §20.3.3 of ESP32-S3 technical manual + * 1. Lock the hardware so no-one else uses it and wait until it is ready. + * 2. Enable/disable interrupt that signals completion -- we don't use the interrupt. + * 3. Write number of words required for result to the RSA_MODE_REG (now called RSA_LENGTH_REG). + * Number of words required for the result is 2 * words for operand - 1 + * 4. Load X, Y operands to memory blocks. Note the Y value must be written to + * right aligned. + * 5. Start the operation by writing 1 to RSA_MULT_START_REG, then wait for it + * to complete by monitoring RSA_IDLE_REG (which is now called RSA_QUERY_INTERRUPT_REG). + * 6. Read the result out. + * 7. Release the hardware lock so others can use it. + * x. Clear the interrupt flag, if you used it (we don't). */ + + /* 1. lock hw for use & wait until it is ready. */ + if ((ret = esp_mp_hw_lock()) != MP_OKAY + || (ret = esp_mp_hw_wait_clean()) != MP_OKAY) + { + return ret; + } + + /* 2. Disable completion interrupt singal; we don't use. */ + DPORT_REG_WRITE(RSA_INTERRUPT_REG, 0); // 0 => no interrupt; 1 => interrupt on completion. + + /* 3. Write number of words required for result. */ + if (nWordsForOperand * BITS_IN_ONE_WORD * 2 > ESP_HW_RSAMAX_BIT) + { + ESP_LOGW(TAG, "result exceeds max bit length"); + return -2; + } + DPORT_REG_WRITE(RSA_LENGTH_REG, (nWordsForOperand * 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, nBitsInX, nWordsForOperand); + esp_mpint_to_memblock(RSA_MEM_Z_BLOCK_BASE + nWordsForOperand * 4, Y, nBitsInY, nWordsForOperand); + + /* 5. Start operation and wait until it completes. */ + process_start(RSA_MULT_START_REG); + ret = wait_until_done(RSA_QUERY_INTERRUPT_REG); + if (MP_OKAY != ret) + { + return ret; + } + + /* 6. read the result form MEM_Z */ + esp_memblock_to_mpint(RSA_MEM_Z_BLOCK_BASE, Z, nWordsForResult); + + /* 7. clear and release hw */ + esp_mp_hw_unlock(); + + Z->sign = (Z->used > 0) ? neg : MP_ZPOS; + + return ret; +#else word32 Xs; word32 Ys; word32 Zs; @@ -356,7 +462,7 @@ int esp_mp_mul(fp_int* X, fp_int* Y, fp_int* Z) process_start(RSA_MULT_START_REG); /* step.4,5 wait until done */ - ret = wait_uitil_done(RSA_INTERRUPT_REG); + ret = wait_until_done(RSA_INTERRUPT_REG); if (ret != MP_OKAY) { ESP_LOGE(TAG, "wait_uitil_done failed."); return ret; @@ -370,6 +476,7 @@ int esp_mp_mul(fp_int* X, fp_int* Y, fp_int* Z) Z->sign = (Z->used > 0) ? neg : MP_ZPOS; return ret; +#endif } /* Z = X * Y (mod M) */ @@ -411,13 +518,19 @@ int esp_mp_mulmod(fp_int* X, fp_int* Y, fp_int* M, fp_int* Z) * where: R = b^n, and b = 2^32 * accordingly R^2 = 2^(n*32*2) */ +#if CONFIG_IDF_TARGET_ESP32S3 + word32 Exponent = maxWords_sz * BITS_IN_ONE_WORD * 2; +#else + word32 Exponent = hwWords_sz << 6; +#endif ret = mp_init_multi(&tmpZ, &r_inv, NULL, NULL, NULL, NULL); - if (ret == 0 && (ret = esp_get_rinv(&r_inv, M, (hwWords_sz << 6))) != MP_OKAY) { + if (ret == 0 && (ret = esp_get_rinv(&r_inv, M, Exponent)) != MP_OKAY) { ESP_LOGE(TAG, "calculate r_inv failed."); mp_clear(&tmpZ); mp_clear(&r_inv); return ret; } + /* lock hw for use */ if ((ret = esp_mp_hw_lock()) != MP_OKAY) { mp_clear(&tmpZ); @@ -431,6 +544,82 @@ int esp_mp_mulmod(fp_int* X, fp_int* Y, fp_int* M, fp_int* Z) mp_clear(&r_inv); return -1; } + +#if CONFIG_IDF_TARGET_ESP32S3 + /* Steps to perform large number modular multiplication. Calculates Z = (X x Y) modulo M. + * The number of bits in the operands (X, Y) is N. N can be 32x, where x = {1,2,3,...64}, so the + * maximum number of bits in the X and Y is 2048. We must use the same number of words to represent + * the bits in X, Y and M. + * See §20.3.3 of ESP32-S3 technical manual + * 1. Wait until the hardware is ready. + * 2. Enable/disable interrupt that signals completion -- we don't use the interrupt. + * 3. Write the number of words required to represent the operands to the + * RSA_MODE_REG (now called RSA_LENGTH_REG). + * 4. Write M' value into RSA_M_PRIME_REG (now called RSA_M_DASH_REG). + * 5. Load X, Y, M, r' operands to memory blocks. + * 6. Start the operation by writing 1 to RSA_MOD_MULT_START_REG, then wait for it + * to complete by monitoring RSA_IDLE_REG (which is now called RSA_QUERY_INTERRUPT_REG). + * 7. Read the result out. + * 8. Release the hardware lock so others can use it. + * x. Clear the interrupt flag, if you used it (we don't). */ + + /* 1. Wait until hardware is ready. */ + if ((ret = esp_mp_hw_wait_clean()) != MP_OKAY) + { + return ret; + } + + /* 2. Disable completion interrupt singal; we don't use. */ + DPORT_REG_WRITE(RSA_INTERRUPT_REG, 0); // 0 => no interrupt; 1 => interrupt on completion. + + /* 3. Write (N_result_bits/32 - 1) to the RSA_MODE_REG. */ + uint32_t uOperandBits = max(max(Xs, Ys), Ms); + if (uOperandBits > ESP_HW_MULTI_RSAMAX_BITS) + { + ESP_LOGW(TAG, "result exceeds max bit length"); + return -2; + } + int nWordsForOperand = bits2words(uOperandBits); + DPORT_REG_WRITE(RSA_LENGTH_REG, nWordsForOperand - 1); + + /* 4. Write M' value into RSA_M_PRIME_REG (now called RSA_M_DASH_REG) */ + DPORT_REG_WRITE(RSA_M_DASH_REG, mp); + + /* Select acceleration options. */ + DPORT_REG_WRITE(RSA_CONSTANT_TIME_REG, 0); + + /* 5. Load X, Y, M, r' operands. + * Note RSA_MEM_RB_BLOCK_BASE == RSA_MEM_Z_BLOC_BASE on ESP32s3*/ + esp_mpint_to_memblock(RSA_MEM_X_BLOCK_BASE, X, Xs, hwWords_sz); + esp_mpint_to_memblock(RSA_MEM_Y_BLOCK_BASE, Y, Ys, hwWords_sz); + esp_mpint_to_memblock(RSA_MEM_M_BLOCK_BASE, M, Ms, hwWords_sz); + esp_mpint_to_memblock(RSA_MEM_RB_BLOCK_BASE, &r_inv, mp_count_bits(&r_inv), hwWords_sz); + + /* 6. Start operation and wait until it completes. */ + process_start(RSA_MOD_MULT_START_REG); + ret = wait_until_done(RSA_QUERY_INTERRUPT_REG); + if (MP_OKAY != ret) + { + return ret; + } + + /* 7. read the result form MEM_Z */ + esp_memblock_to_mpint(RSA_MEM_Z_BLOCK_BASE, &tmpZ, zwords); + + /* 8. clear and release hw */ + esp_mp_hw_unlock(); + + if (negcheck) { + mp_sub(M, &tmpZ, &tmpZ); + } + + mp_copy(&tmpZ, Z); + mp_clear(&tmpZ); + mp_clear(&r_inv); + + return ret; +#else + /*Steps to use hw in the following order: * 1. wait until clean hw engine * 2. Write(N/512bits - 1) to MULT_MODE_REG @@ -466,11 +655,12 @@ int esp_mp_mulmod(fp_int* X, fp_int* Y, fp_int* M, fp_int* Z) /* step.3 write M' into memory */ DPORT_REG_WRITE(RSA_M_DASH_REG, mp); + /* step.4 start process */ process_start(RSA_MULT_START_REG); /* step.5,6 wait until done */ - wait_uitil_done(RSA_INTERRUPT_REG); + wait_until_done(RSA_INTERRUPT_REG); /* step.7 Y to MEM_X */ esp_mpint_to_memblock(RSA_MEM_X_BLOCK_BASE, Y, Ys, hwWords_sz); @@ -478,7 +668,7 @@ int esp_mp_mulmod(fp_int* X, fp_int* Y, fp_int* M, fp_int* Z) process_start(RSA_MULT_START_REG); /* step.9,11 wait until done */ - wait_uitil_done(RSA_INTERRUPT_REG); + wait_until_done(RSA_INTERRUPT_REG); /* step.12 read the result from MEM_Z */ esp_memblock_to_mpint(RSA_MEM_Z_BLOCK_BASE, &tmpZ, zwords); @@ -502,23 +692,25 @@ int esp_mp_mulmod(fp_int* X, fp_int* Y, fp_int* M, fp_int* Z) mp_clear(&r_inv); return ret; +#endif } /* Large Number Modular Exponentiation * * Z = X^Y mod M * - * See Chapter 24: - * https://www.espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf - * + * See: + * ESP32, Chapter 24, https://www.espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf + * ESP32s3, section 20.3.1, https://www.espressif.com/sites/default/files/documentation/esp32-s3_technical_reference_manual_en.pdf * The operation is based on Montgomery multiplication. Aside from the * arguments X, Y , and M, two additional ones are needed —r and M′ .* These arguments are calculated in advance by software. .* .* The RSA Accelerator supports operand lengths of N ∈ {512, 1024, 1536, 2048, -.* 2560, 3072, 3584, 4096} bits. The bit length of arguments Z, X, Y , M, -.* and r can be any one from the N set, but all numbers in a calculation must -.* be of the same length. The bit length of M′ is always 32. +.* 2560, 3072, 3584, 4096} bits on the ESP32 and N ∈ [32, 4096] bits on the ESP32s3. +.* The bit length of arguments Z, X, Y , M, and r can be any one from the N set, +.* but all numbers in a calculation must be of the same length. +.* The bit length of M′ is always 32. .* .* Note some DH references may use: Y = (G ^ X) mod P */ @@ -568,6 +760,70 @@ int esp_mp_exptmod(fp_int* X, fp_int* Y, word32 Ys, fp_int* M, fp_int* Z) return -1; } +#if CONFIG_IDF_TARGET_ESP32S3 + /* Steps to perform large number modular exponentiation. Calculates Z = (X ^ Y) modulo M. + * The number of bits in the operands (X, Y) is N. N can be 32x, where x = {1,2,3,...64}, so the + * maximum number of bits in the X and Y is 2048. + * See §20.3.3 of ESP32-S3 technical manual + * 1. Wait until the hardware is ready. + * 2. Enable/disable interrupt that signals completion -- we don't use the interrupt. + * 3. Write (N_bits/32 - 1) to the RSA_MODE_REG (now called RSA_LENGTH_REG). + * Here N_bits is the maximum number of bits in X, Y and M. + * 4. Write M' value into RSA_M_PRIME_REG (now called RSA_M_DASH_REG). + * 5. Load X, Y, M, r' operands to memory blocks. + * 6. Start the operation by writing 1 to RSA_MODEXP_START_REG, then wait for it + * to complete by monitoring RSA_IDLE_REG (which is now called RSA_QUERY_INTERRUPT_REG). + * 7. Read the result out. + * 8. Release the hardware lock so others can use it. + * x. Clear the interrupt flag, if you used it (we don't). */ + + /* 1. Wait until hardware is ready. */ + if ((ret = esp_mp_hw_wait_clean()) != MP_OKAY) + { + return ret; + } + + /* 2. Disable completion interrupt singal; we don't use. */ + DPORT_REG_WRITE(RSA_INTERRUPT_REG, 0); // 0 => no interrupt; 1 => interrupt on completion. + + /* 3. Write (N_result_bits/32 - 1) to the RSA_MODE_REG. */ + uint32_t uOperandBits = max(max(Xs, Ys), Ms); + if (uOperandBits > ESP_HW_MULTI_RSAMAX_BITS) + { + ESP_LOGW(TAG, "result exceeds max bit length"); + return -2; + } + int nWordsForOperand = bits2words(uOperandBits); + DPORT_REG_WRITE(RSA_LENGTH_REG, nWordsForOperand - 1); + + /* 4. Write M' value into RSA_M_PRIME_REG (now called RSA_M_DASH_REG) */ + DPORT_REG_WRITE(RSA_M_DASH_REG, mp); + + /* 5. Load X, Y, M, r' operands. */ + esp_mpint_to_memblock(RSA_MEM_X_BLOCK_BASE, X, Xs, hwWords_sz); + esp_mpint_to_memblock(RSA_MEM_Y_BLOCK_BASE, Y, Ys, hwWords_sz); + esp_mpint_to_memblock(RSA_MEM_M_BLOCK_BASE, M, Ms, hwWords_sz); + esp_mpint_to_memblock(RSA_MEM_Z_BLOCK_BASE, &r_inv, mp_count_bits(&r_inv), hwWords_sz); + + /* 6. Start operation and wait until it completes. */ + process_start(RSA_MODEXP_START_REG); + ret = wait_until_done(RSA_QUERY_INTERRUPT_REG); + if (MP_OKAY != ret) + { + return ret; + } + + /* 7. read the result form MEM_Z */ + esp_memblock_to_mpint(RSA_MEM_Z_BLOCK_BASE, Z, BITS_TO_WORDS(Ms)); + + /* 8. clear and release hw */ + esp_mp_hw_unlock(); + + mp_clear(&r_inv); + + return ret; +#else + /*Steps to use hw in the following order: * 1. Write(N/512bits - 1) to MODEXP_MODE_REG * 2. Write X, Y, M and r_inv to memory blocks @@ -600,7 +856,7 @@ int esp_mp_exptmod(fp_int* X, fp_int* Y, word32 Ys, fp_int* M, fp_int* Z) process_start(RSA_START_MODEXP_REG); /* step.5 wait until done */ - wait_uitil_done(RSA_INTERRUPT_REG); + wait_until_done(RSA_INTERRUPT_REG); /* step.6 read a result form memory */ esp_memblock_to_mpint(RSA_MEM_Z_BLOCK_BASE, Z, BITS_TO_WORDS(Ms)); /* step.7 clear and release hw */ @@ -609,6 +865,7 @@ int esp_mp_exptmod(fp_int* X, fp_int* Y, word32 Ys, fp_int* M, fp_int* Z) mp_clear(&r_inv); return ret; +#endif } #endif /* !NO_RSA || HAVE_ECC */ diff --git a/wolfcrypt/src/port/Espressif/esp32_sha.c b/wolfcrypt/src/port/Espressif/esp32_sha.c index 257a715287..ee2699c388 100644 --- a/wolfcrypt/src/port/Espressif/esp32_sha.c +++ b/wolfcrypt/src/port/Espressif/esp32_sha.c @@ -37,9 +37,11 @@ #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 */ - +/* Espressif hardware abstraction layers: + * https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/api-guides/hardware-abstraction.html + * Espressif note their HAL API is experimental and may change between minor releases. */ +#include /* peripheral clock/reset control */ + #include #include #include @@ -123,12 +125,19 @@ static word32 wc_esp_sha_digest_size(enum SHA_TYPE type) */ static void wc_esp_wait_until_idle() { +#if CONFIG_IDF_TARGET_ESP32S3 + while (REG_READ(SHA_BUSY_REG)) + { + /* wait patiently for the SHA to be available. */ + } +#else while((DPORT_REG_READ(SHA_1_BUSY_REG) != 0) || (DPORT_REG_READ(SHA_256_BUSY_REG) != 0) || (DPORT_REG_READ(SHA_384_BUSY_REG) != 0) || (DPORT_REG_READ(SHA_512_BUSY_REG) != 0)) { /* do nothing while waiting. */ } +#endif } /* @@ -149,18 +158,25 @@ 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 */ +#if CONFIG_IDF_TARGET_ESP32S3 /* once the value we read is a 0 in the DPORT_PERI_CLK_EN_REG bit * then we have fully unrolled the enables via ref_counts[periph]==0 */ - while ((this_sha_mask & *(uint32_t*)DPORT_PERI_CLK_EN_REG) != 0) { + while (periph_ll_periph_enabled(PERIPH_SHA_MODULE)) +#else + /* this is the bit-mask for our SHA CLK_EN_REG */ + uint32_t this_sha_mask = periph_ll_get_clk_en_mask(PERIPH_SHA_MODULE); + + /* 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) +#endif + { periph_module_disable(PERIPH_SHA_MODULE); actual_unroll_count++; ESP_LOGI(TAG, "unroll not yet successful. try #%d", @@ -193,8 +209,10 @@ int esp_unroll_sha_module_enable(WC_ESP32SHA* ctx) } /* -* lock hw engine. +* lock hw engine, or fallback to software calculations if the hardware is busy. * this should be called before using engine. +* Note: we are assuming all users of the SHA engine will access it through +* the Wolf libraries. */ int esp_sha_try_hw_lock(WC_ESP32SHA* ctx) { @@ -346,6 +364,59 @@ static int esp_sha_start_process(WC_ESP32SHA* sha) ESP_LOGV(TAG, " enter esp_sha_start_process"); +#if CONFIG_IDF_TARGET_ESP32S3 + + /* Translate from Wolf sha type to hardware algorithm. */ + uint8_t uHardwareAlgorithm = 0; + switch (sha->sha_type) + { + case SHA1: + uHardwareAlgorithm = 0; + break; + case SHA2_256: + uHardwareAlgorithm = 2; + break; +#if defined(WOLFSSL_SHA384) + case SHA2_384: + uHardwareAlgorithm = 3; + break; +#endif +#if defined(WOLFSSL_SHA512) + case SHA2_512: + uHardwareAlgorithm = 4; + break; +#endif + default: + /* Unsupported sha mode. */ + sha->mode = ESP32_SHA_FAIL_NEED_UNROLL; + return -1; + } + + REG_WRITE(SHA_MODE_REG, uHardwareAlgorithm); + + if (sha->isfirstblock) + { + REG_WRITE(SHA_START_REG, 1); + sha->isfirstblock = 0; + + ESP_LOGV(TAG, " set sha->isfirstblock = 0"); + +#if defined(DEBUG_WOLFSSL) + this_block_num = 1; /* one-based counter, just for debug info */ +#endif + + } + else + { + REG_WRITE(SHA_CONTINUE_REG, 1); + +#if defined(DEBUG_WOLFSSL) + this_block_num++; /* one-based counter */ + ESP_LOGV(TAG, " continue block #%d", this_block_num); +#endif + } + +#else if(sha->isfirstblock){ /* start registers for first message block * we don't make any relational memory position assumptions. @@ -424,6 +495,7 @@ static int esp_sha_start_process(WC_ESP32SHA* sha) #endif } +#endif ESP_LOGV(TAG, " leave esp_sha_start_process"); @@ -437,7 +509,6 @@ static void wc_esp_process_block(WC_ESP32SHA* ctx, /* see ctx->sha_type */ const word32* data, word32 len) { - int i; int word32_to_save = (len) / (sizeof(word32)); ESP_LOGV(TAG, " enter esp_process_block"); if (word32_to_save > 0x31) { @@ -445,10 +516,26 @@ static void wc_esp_process_block(WC_ESP32SHA* ctx, /* see ctx->sha_type */ ESP_LOGE(TAG, " ERROR esp_process_block len exceeds 0x31 words"); } - /* check if there are any busy engine */ + /* wait until the engine is available */ wc_esp_wait_until_idle(); /* load [len] words of message data into hw */ +#if CONFIG_IDF_TARGET_ESP32S3 + uint32_t *pMessageSource = (uint32_t *)data; + uint32_t *pAcceleratorMessage = (uint32_t *)(SHA_TEXT_BASE); + while (word32_to_save--) + { + /* Must swap endiness of data loaded into harware accelerator to produce + * correct result. Using DPORT_REG_WRITE doesn't avoid this for ESP32s3. + * Note: data sheet claims we also need to swap endian across 64 byte words + * when doing SHA-512, but the SHA-512 result is not correct if you do that. */ + DPORT_REG_WRITE(pAcceleratorMessage, __builtin_bswap32(*pMessageSource)); + ++pAcceleratorMessage; + ++pMessageSource; + } + +#else + int i; for (i = 0; i < word32_to_save; i++) { /* by using DPORT_REG_WRITE, we avoid the need * to call __builtin_bswap32 to address endiness @@ -461,12 +548,13 @@ static void wc_esp_process_block(WC_ESP32SHA* ctx, /* see ctx->sha_type */ DPORT_REG_WRITE(SHA_TEXT_BASE + (i*sizeof(word32)), *(data + i)); /* 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 */ esp_sha_start_process(ctx); - + ESP_LOGV(TAG, " leave esp_process_block"); } @@ -492,6 +580,43 @@ int wc_esp_digest_state(WC_ESP32SHA* ctx, byte* hash) return -1; } +#if CONFIG_IDF_TARGET_ESP32S3 + if (ctx->isfirstblock == 1) + { + /* no hardware use yet. Nothing to do yet */ + return 0; + } + + /* wait until idle */ + wc_esp_wait_until_idle(); + + /* read hash result into buffer & flip endiness */ + uint32_t* pHashDestination = (uint32_t*)hash; + size_t szHashWords = wc_esp_sha_digest_size(ctx->sha_type) / sizeof(uint32_t); + esp_dport_access_read_buffer(pHashDestination, SHA_H_BASE, szHashWords); + + if (ctx->sha_type == SHA2_512) + { + /* Although we don't have to swap endian on 64-bit words at the input, + * we do for the output. */ + size_t szHash64Words = szHashWords / 2; + uint64_t *pHash64Buffer = (uint64_t*)pHashDestination; + while (szHash64Words--) + { + *pHash64Buffer = __builtin_bswap64(*pHash64Buffer); + ++pHash64Buffer; + } + } + else + { + while (szHashWords--) + { + *pHashDestination = __builtin_bswap32(*pHashDestination); + ++pHashDestination; + } + } +#else + /* wait until idle */ wc_esp_wait_until_idle(); @@ -558,6 +683,8 @@ int wc_esp_digest_state(WC_ESP32SHA* ctx, byte* hash) 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 (ctx->sha_type == SHA2_384 || ctx->sha_type == SHA2_512) { @@ -571,7 +698,8 @@ int wc_esp_digest_state(WC_ESP32SHA* ctx, byte* hash) } } #endif - +#endif + ESP_LOGV(TAG, "leave esp_digest_state"); return 0; } diff --git a/wolfssl/wolfcrypt/port/Espressif/esp32-crypt.h b/wolfssl/wolfcrypt/port/Espressif/esp32-crypt.h index 72b16d8bec..205fcce508 100644 --- a/wolfssl/wolfcrypt/port/Espressif/esp32-crypt.h +++ b/wolfssl/wolfcrypt/port/Espressif/esp32-crypt.h @@ -51,7 +51,9 @@ #include "driver/periph_ctrl.h" #endif -#if ESP_IDF_VERSION_MAJOR >= 4 +#if ESP_IDF_VERSION_MAJOR >= 5 + // ets_sys.h isn't required for ESP32; breaks ESP32s3 build. +#elif ESP_IDF_VERSION_MAJOR >= 4 #include #else #include