From afac19dc93aec556951c5b778f45fbe09896d1d2 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Wed, 27 Dec 2023 18:57:35 -0800 Subject: [PATCH 1/5] Nucleus Patch 1. Nucleus builds changed the source file names to have a wolfssh_ prefix. Take that into account for misc.c. 2. Change CleanPath to add a delimiter to the input string. 3. Reorganize the WS_GETtime macros to clean up adding specific items for Nucleus. 4. Add some typecasting on some sizeof. 5. Some whitespace cleanup, and removing a redundant include. --- src/internal.c | 8 +++++++- src/ssh.c | 6 +++++- src/wolfsftp.c | 32 ++++++++++++++++++++++++++------ wolfssh/port.h | 18 +++++++++++++----- 4 files changed, 51 insertions(+), 13 deletions(-) diff --git a/src/internal.c b/src/internal.c index 7e9727cf6..34e27f2f5 100644 --- a/src/internal.c +++ b/src/internal.c @@ -54,7 +54,11 @@ #include #else #define WOLFSSH_MISC_INCLUDED - #include "src/misc.c" + #if defined(WOLFSSL_NUCLEUS) + #include "src/wolfssh_misc.c" + #else + #include "src/misc.c" + #endif #endif @@ -13849,6 +13853,8 @@ int wolfSSH_CleanPath(WOLFSSH* ssh, char* in) if (path[sz - 1] == ':') { path[sz] = WS_DELIM; path[sz + 1] = '\0'; + in[sz] = WS_DELIM; + in[sz + 1] = '\0'; } /* clean up any multiple drive listed i.e. A:/A: */ diff --git a/src/ssh.c b/src/ssh.c index 4e3758d72..a2fe0e91e 100644 --- a/src/ssh.c +++ b/src/ssh.c @@ -39,7 +39,11 @@ #include #else #define WOLFSSH_MISC_INCLUDED - #include "src/misc.c" + #if defined(WOLFSSL_NUCLEUS) + #include "src/wolfssh_misc.c" + #else + #include "src/misc.c" + #endif #endif #ifdef HAVE_FIPS diff --git a/src/wolfsftp.c b/src/wolfsftp.c index e32d09d04..0d62ade4a 100644 --- a/src/wolfsftp.c +++ b/src/wolfsftp.c @@ -34,7 +34,11 @@ #include #else #define WOLFSSH_MISC_INCLUDED - #include "src/misc.c" + #if defined(WOLFSSL_NUCLEUS) + #include "src/wolfssh_misc.c" + #else + #include "src/misc.c" + #endif #endif /* for XGMTIME if defined */ @@ -2731,6 +2735,15 @@ static int wolfSSH_SFTPNAME_readdir(WOLFSSH* ssh, WDIR* dir, WS_SFTPNAME* out, ret = WS_NEXT_ERROR; } + if (special) { + sz = WSTRLEN(out->fName); + + if ((out->fName[sz - 1] == '/') || (out->fName[sz - 1] == WS_DELIM)) { + out->fName[sz - 1] = '\0'; + out->fSz--; + } + } + /* Use attributes and fName to create long name */ if (SFTP_CreateLongName(out) != WS_SUCCESS) { WLOG(WS_LOG_DEBUG, "Error creating long name for %s", out->fName); @@ -4271,12 +4284,22 @@ int SFTP_RemoveHandleNode(WOLFSSH* ssh, byte* handle, word32 handleSz) #ifndef NO_WOLFSSH_MKTIME #define WS_GETDAY(d) ((d) & 0x001f) -#define WS_GETMON(d) (((d) >> 5) & 0x000f) +#define _GETMON(d) (((d) >> 5) & 0x000f) /* number of years since 1900. year + 1980 - 1900 */ #define WS_GETYEAR(d) ((((d) >> 9) & 0x007f) + 80) -#define WS_GETHOUR(t) (((t) >> 11) & 0x001f) +#define _GETHOUR(t) (((t) >> 11) & 0x001f) #define WS_GETMIN(t) (((t) >> 5 ) & 0x003f) #define WS_GETSEC(t) (((t) << 1 ) & 0x003f) +#ifdef WOLFSSL_NUCLEUS + /* mktime() expects month from 0 to 11. Nucleus months + * are saved as 1 to 12. Hence 1 is being deducted to + * make it compatible with Unix time stamp. */ + #define WS_GETMON(d) (_GETMON(d) - 5) + #define WS_GETHOUR(t) (_GETHOUR(t) - 1) +#else + #define WS_GETMON(d) _GETMON(d) + #define WS_GETHOUR(t) _GETHOUR(t) +#endif /* convert nucleus date and time shorts to word32 * returns results in Unix time stamp */ @@ -7159,7 +7182,6 @@ int wolfSSH_SFTP_SendWritePacket(WOLFSSH* ssh, byte* handle, word32 handleSz, ret = wolfSSH_worker(ssh, NULL); continue; /* skip past rest and send more */ } - if (state->sentSz <= 0) { ssh->error = state->sentSz; ret = WS_FATAL_ERROR; @@ -8901,7 +8923,6 @@ int wolfSSH_SFTP_Put(WOLFSSH* ssh, char* from, char* to, byte resume, } } - /* called when wolfSSH_free() is called * return WS_SUCCESS on success */ int wolfSSH_SFTP_free(WOLFSSH* ssh) @@ -8950,7 +8971,6 @@ int wolfSSH_SFTP_free(WOLFSSH* ssh) return WS_SUCCESS; } - #ifdef WOLFSSH_SHOW_SIZES void wolfSSH_SFTP_ShowSizes(void) diff --git a/wolfssh/port.h b/wolfssh/port.h index 189109c63..3a4820efd 100644 --- a/wolfssh/port.h +++ b/wolfssh/port.h @@ -33,6 +33,10 @@ #include #include +#ifdef WOLFSSL_NUCLEUS +#include "os/networking/utils/util_tp.h" +#endif + #ifdef __cplusplus extern "C" { #endif @@ -105,14 +109,16 @@ extern "C" { #define WFILE int WOLFSSH_API int wfopen(WFILE**, const char*, const char*); - #define WFOPEN(fs, f,fn,m) wfopen((f),(fn),(m)) + #define WFOPEN(fs,f,fn,m) wfopen((f),(fn),(m)) #define WFCLOSE(fs,f) NU_Close(*(f)) - #define WFWRITE(fs,b,x,s,f) ((s) != 0)? NU_Write(*(f),(const CHAR*)(b),(s)): 0 + #define WFWRITE(fs,b,x,s,f) \ + (((s) != 0) ? NU_Write(*(f),(const CHAR*)(b),(s)) : 0) #define WFREAD(fs,b,x,s,f) NU_Read(*(f),(CHAR*)(b),(s)) #define WFSEEK(fs,s,o,w) NU_Seek(*(s),(o),(w)) #define WFTELL(fs,s) NU_Seek(*(s), 0, PSEEK_CUR) #define WREWIND(fs,s) NU_Seek(*(s), 0, PSEEK_SET) #define WSEEK_END PSEEK_END + #define WBADFILE NULL #define WS_DELIM '\\' #define WOLFSSH_O_RDWR PO_RDWR @@ -561,6 +567,9 @@ extern "C" { #elif defined(WOLFSSH_ZEPHYR) #define WTIME time #define WLOCALTIME(c,r) (gmtime_r((c),(r))!=NULL) +#elif defined(WOLFSSL_NUCLEUS) + #define WTIME time + #define WLOCALTIME(c,r) (localtime_s((c),(r))!=NULL) #else #define WTIME time #define WLOCALTIME(c,r) (localtime_r((c),(r))!=NULL) @@ -756,7 +765,7 @@ extern "C" { if (NU_Get_Attributes(&atrib, dir) == NU_SUCCESS) { if (atrib & ADIRENT) { if (tmp[idx-1] != WS_DELIM) { - if (idx + 2 > sizeof(tmp)) { + if (idx + 2 > (int)sizeof(tmp)) { /* not enough space */ return -1; } @@ -768,7 +777,7 @@ extern "C" { } if (tmp[idx - 1] == WS_DELIM) { - if (idx + 1 > sizeof(tmp)) { + if (idx + 1 > (int)sizeof(tmp)) { /* not enough space */ return -1; } @@ -1316,7 +1325,6 @@ extern "C" { #include /* used for rmdir */ #include /* used for mkdir, stat, and lstat */ #include /* used for remove and rename */ - #include /* used for opening directory and reading */ #define WSTAT_T struct stat #define WRMDIR(fs,d) rmdir((d)) From 27275b76f3848f31f46e4e31642ea033fdd2fb44 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Wed, 6 Dec 2023 09:32:37 -0800 Subject: [PATCH 2/5] SFTP Test File Modify the SFTP tests to use the file configure.ac instead of configure. Some environments do not have or use configure. Configure.ac is in the source archive. --- tests/sftp.c | 14 +++++++------- zephyr/samples/tests/tests.c | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/sftp.c b/tests/sftp.c index 36b2cb081..1e4aa067e 100644 --- a/tests/sftp.c +++ b/tests/sftp.c @@ -44,17 +44,17 @@ static const char* cmds[] = { "pwd", "ls", #ifdef WOLFSSH_ZEPHYR - "put " CONFIG_WOLFSSH_SFTP_DEFAULT_DIR "/configure", + "put " CONFIG_WOLFSSH_SFTP_DEFAULT_DIR "/configure.ac", #else - "put configure", + "put configure.ac", #endif "ls", #ifdef WOLFSSH_ZEPHYR - "get configure " CONFIG_WOLFSSH_SFTP_DEFAULT_DIR "/test-get", + "get configure.ac " CONFIG_WOLFSSH_SFTP_DEFAULT_DIR "/test-get", #else - "get configure test-get", + "get configure.ac test-get", #endif - "rm configure", + "rm configure.ac", "cd ../", "ls", "rename test-get test-get-2", @@ -116,8 +116,8 @@ static int Expected(int command) } case 6: - if (WSTRNSTR(inBuf, "configure", sizeof(inBuf)) == NULL) { - fprintf(stderr, "configure not found in %s\n", inBuf); + if (WSTRNSTR(inBuf, "configure.ac", sizeof(inBuf)) == NULL) { + fprintf(stderr, "configure.ac not found in %s\n", inBuf); return 1; } else { diff --git a/zephyr/samples/tests/tests.c b/zephyr/samples/tests/tests.c index 2f57aa092..56d18c91b 100644 --- a/zephyr/samples/tests/tests.c +++ b/zephyr/samples/tests/tests.c @@ -81,7 +81,7 @@ int main(void) /* Setup the necessary files for the sftp tests */ fs_file_t_init(&zfp); snprintf(filename, sizeof(filename), "%s/%s", - CONFIG_WOLFSSH_SFTP_DEFAULT_DIR, "configure"); + CONFIG_WOLFSSH_SFTP_DEFAULT_DIR, "configure.ac"); CHECK_TEST_RETURN(fs_open(&zfp, filename, FS_O_WRITE|FS_O_CREATE)); /* Write some random data to file */ for (i = 0; i < 10; i++) From 10e7cd8d7260dd572fa7c68f061fa581c235558c Mon Sep 17 00:00:00 2001 From: gojimmypi Date: Thu, 11 Jan 2024 16:37:13 -0800 Subject: [PATCH 3/5] Espressif examples: template and echoserver --- ide/Espressif/ESP-IDF/examples/README.md | 5 + .../wolfssh_echoserver/CMakeLists.txt | 129 + .../examples/wolfssh_echoserver/README.md | 75 + .../wolfssh_echoserver_IDF_v5.1_ESP32.sln | 37 + ...wolfssh_echoserver_IDF_v5.1_ESP32.vgdbproj | 269 ++ .../components/wolfssh/CMakeLists.txt | 545 ++++ .../components/wolfssl/CMakeLists.txt | 676 ++++ .../components/wolfssl/README.md | 9 + .../wolfssl/include/user_settings.h | 508 +++ .../wolfssh_echoserver/main/CMakeLists.txt | 155 + .../wolfssh_echoserver/main/echoserver.c | 2737 +++++++++++++++++ .../main/include/echoserver.h | 35 + .../wolfssh_echoserver/main/include/main.h | 38 + .../main/include/time_helper.h | 54 + .../main/include/wifi_connect.h | 96 + .../examples/wolfssh_echoserver/main/main.c | 182 ++ .../wolfssh_echoserver/main/time_helper.c | 360 +++ .../wolfssh_echoserver/main/wifi_connect.c | 274 ++ .../partitions_singleapp_large.csv | 31 + .../wolfssh_echoserver/sdkconfig.defaults | 38 + .../examples/wolfssh_template/CMakeLists.txt | 83 + .../examples/wolfssh_template/README.md | 64 + .../wolfssh_template_IDF_v5.1_ESP32.sln | 54 + .../wolfssh_template_IDF_v5.1_ESP32.vgdbproj | 269 ++ .../components/wolfssh/CMakeLists.txt | 508 +++ .../components/wolfssl/CMakeLists.txt | 676 ++++ .../components/wolfssl/README.md | 9 + .../wolfssl/include/user_settings.h | 508 +++ .../wolfssh_template/main/CMakeLists.txt | 154 + .../wolfssh_template/main/include/main.h | 38 + .../examples/wolfssh_template/main/main.c | 79 + .../partitions_singleapp_large.csv | 31 + .../wolfssh_template/sdkconfig.defaults | 38 + 33 files changed, 8764 insertions(+) create mode 100644 ide/Espressif/ESP-IDF/examples/README.md create mode 100644 ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/CMakeLists.txt create mode 100644 ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/README.md create mode 100644 ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/VisualGDB/wolfssh_echoserver_IDF_v5.1_ESP32.sln create mode 100644 ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/VisualGDB/wolfssh_echoserver_IDF_v5.1_ESP32.vgdbproj create mode 100644 ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/components/wolfssh/CMakeLists.txt create mode 100644 ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/components/wolfssl/CMakeLists.txt create mode 100644 ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/components/wolfssl/README.md create mode 100644 ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/components/wolfssl/include/user_settings.h create mode 100644 ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/main/CMakeLists.txt create mode 100644 ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/main/echoserver.c create mode 100644 ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/main/include/echoserver.h create mode 100644 ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/main/include/main.h create mode 100644 ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/main/include/time_helper.h create mode 100644 ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/main/include/wifi_connect.h create mode 100644 ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/main/main.c create mode 100644 ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/main/time_helper.c create mode 100644 ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/main/wifi_connect.c create mode 100644 ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/partitions_singleapp_large.csv create mode 100644 ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/sdkconfig.defaults create mode 100644 ide/Espressif/ESP-IDF/examples/wolfssh_template/CMakeLists.txt create mode 100644 ide/Espressif/ESP-IDF/examples/wolfssh_template/README.md create mode 100644 ide/Espressif/ESP-IDF/examples/wolfssh_template/VisualGDB/wolfssh_template_IDF_v5.1_ESP32.sln create mode 100644 ide/Espressif/ESP-IDF/examples/wolfssh_template/VisualGDB/wolfssh_template_IDF_v5.1_ESP32.vgdbproj create mode 100644 ide/Espressif/ESP-IDF/examples/wolfssh_template/components/wolfssh/CMakeLists.txt create mode 100644 ide/Espressif/ESP-IDF/examples/wolfssh_template/components/wolfssl/CMakeLists.txt create mode 100644 ide/Espressif/ESP-IDF/examples/wolfssh_template/components/wolfssl/README.md create mode 100644 ide/Espressif/ESP-IDF/examples/wolfssh_template/components/wolfssl/include/user_settings.h create mode 100644 ide/Espressif/ESP-IDF/examples/wolfssh_template/main/CMakeLists.txt create mode 100644 ide/Espressif/ESP-IDF/examples/wolfssh_template/main/include/main.h create mode 100644 ide/Espressif/ESP-IDF/examples/wolfssh_template/main/main.c create mode 100644 ide/Espressif/ESP-IDF/examples/wolfssh_template/partitions_singleapp_large.csv create mode 100644 ide/Espressif/ESP-IDF/examples/wolfssh_template/sdkconfig.defaults diff --git a/ide/Espressif/ESP-IDF/examples/README.md b/ide/Espressif/ESP-IDF/examples/README.md new file mode 100644 index 000000000..63ebbdd7f --- /dev/null +++ b/ide/Espressif/ESP-IDF/examples/README.md @@ -0,0 +1,5 @@ +# wolfSSL Espressif Managed Component examples + +[wolfssh_template](./wolfssh_template/README.md) + +[wolfssh_echoserver](./wolfssh_echoserver/README.md) \ No newline at end of file diff --git a/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/CMakeLists.txt b/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/CMakeLists.txt new file mode 100644 index 000000000..2b754ab8f --- /dev/null +++ b/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/CMakeLists.txt @@ -0,0 +1,129 @@ +# [wolfSSL Project]/CMakeLists.txt +# +# Copyright (C) 2006-2023 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 2 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 this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA +# +# cmake for WOLFSSH Espressif projects +# +# See https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/build-system.html + +# wolfSSL Espressif Example Project CMakeLists.txt +# v1.0 +# +# The following lines of boilerplate have to be in your project's +# CMakeLists in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.16) + +# enable wolfssl user_settings.h project-wide +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DWOLFSSL_USER_SETTINGS") +set(WOLFSSL_USER_SETTINGS ON) + +# Assume we have a ESP_ENABLE_WOLFSSH section in user_settings.h +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DESP_ENABLE_WOLFSSH") + +# The wolfSSL CMake file should be able to find the source code. +# Otherwise, assign an environment variable or set it here: +# +# set(WOLFSSL_ROOT "~/workspace/wolfssl-other-source") +# set(WOLFSSH_ROOT "~/workspace/wolfssh-other-source") +# set(WOLFSSL_ROOT "C:/workspace/wolfssl-master") + +# Optional WOLFSSL_CMAKE_SYSTEM_NAME detection to find +# USE_MY_PRIVATE_CONFIG path for my_private_config.h +# +# Expected path varies: +# +# WSL: /mnt/c/workspace +# Linux: ~/workspace +# Windows: C:\workspace +# +if(WIN32) + # Windows-specific configuration here + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DWOLFSSL_CMAKE_SYSTEM_NAME_WINDOWS") + message("Detected Windows") +endif() +if(CMAKE_HOST_UNIX) + message("Detected UNIX") +endif() +if(APPLE) + message("Detected APPLE") +endif() +if(CMAKE_HOST_UNIX AND (NOT APPLE) AND EXISTS "/proc/sys/fs/binfmt_misc/WSLInterop") + # Windows-specific configuration here + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DWOLFSSL_CMAKE_SYSTEM_NAME_WSL") + message("Detected WSL") +endif() +if(CMAKE_HOST_UNIX AND (NOT APPLE) AND (NOT WIN32)) + # Windows-specific configuration here + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DWOLFSSL_CMAKE_SYSTEM_NAME_LINUX") + message("Detected Linux") +endif() +if(APPLE) + # Windows-specific configuration here + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DWOLFSSL_CMAKE_SYSTEM_NAME_APPLE") + message("Detected Apple") +endif() +# End optional WOLFSSL_CMAKE_SYSTEM_NAME + +# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. +set (PROTOCOL_EXAMPLES_DIR $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) + +if (EXISTS "${PROTOCOL_EXAMPLES_DIR}") + message("Found PROTOCOL_EXAMPLES_DIR=${PROTOCOL_EXAMPLES_DIR}") + set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DFOUND_PROTOCOL_EXAMPLES_DIR") +else() + message("NOT FOUND: PROTOCOL_EXAMPLES_DIR=${PROTOCOL_EXAMPLES_DIR}") +endif() + +# Check that there are not conflicting wolfSSL components +# The ESP Registry Component will be in ./managed_components/wolfssl__wolfssl +# The local component wolfSSL directory will be in ./components/wolfssl +if( EXISTS "${CMAKE_HOME_DIRECTORY}/managed_components/wolfssl__wolfssl" AND EXISTS "${CMAKE_HOME_DIRECTORY}/components/wolfssl" ) + # These exclude statements don't seem to be honored by the $ENV{IDF_PATH}/tools/cmake/project.cmake' + # add_subdirectory("${CMAKE_HOME_DIRECTORY}/managed_components/wolfssl__wolfssl" EXCLUDE_FROM_ALL) + # add_subdirectory("${CMAKE_HOME_DIRECTORY}/managed_components/wolfssl__wolfssl/include" EXCLUDE_FROM_ALL) + # So we'll error out and let the user decide how to proceed: + message(WARNING "\nFound wolfSSL components in\n" + "./managed_components/wolfssl__wolfssl\n" + "and\n" + "./components/wolfssl\n" + "in project directory: \n" + "${CMAKE_HOME_DIRECTORY}") + message(FATAL_ERROR "\nPlease use either the ESP Registry Managed Component or the wolfSSL component directory but not both.\n" + "If removing the ./managed_components/wolfssl__wolfssl directory, remember to also remove " + "or rename the idf_component.yml file typically found in ./main/") +else() + message(STATUS "No conflicting wolfSSL components found.") +endif() + + +# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. +set (PROTOCOL_EXAMPLES_DIR $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) + +if (EXISTS "${PROTOCOL_EXAMPLES_DIR}") + message("Found PROTOCOL_EXAMPLES_DIR=${PROTOCOL_EXAMPLES_DIR}") + set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DFOUND_PROTOCOL_EXAMPLES_DIR") +else() + message("NOT FOUND: PROTOCOL_EXAMPLES_DIR=${PROTOCOL_EXAMPLES_DIR}") +endif() + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) + +project(wolfssh_echoserver) diff --git a/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/README.md b/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/README.md new file mode 100644 index 000000000..8ed8996cc --- /dev/null +++ b/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/README.md @@ -0,0 +1,75 @@ +# wolfSSL Server Project + +This is an example wolfSSH Server based on the minimally viable wolfSSL [template](../wolfssh_template/README.md) + +See the [command line example client](https://github.com/wolfSSL/wolfssh/tree/master/examples/client) +and the instructions in [wolfssh README.md](https://github.com/wolfSSL/wolfssh#readme) + +To connect: + +```bash +TODO + +ssh -p 22222 jack@192.168.1.32 +``` + +### Prerequisites + +It is assumed the [ESP-IDF environment](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/) has been installed. + +### Files Included + +- [main.c](./main/main.c) with a simple call to an Espressif library (`ESP_LOGI`) and a call to a wolfSSL library (`esp_ShowExtendedSystemInfo`) . + +- See [components/wolfssl/include](./components/wolfssl/include/user_settings.h) directory to edit the wolfSSL `user_settings.h`. + +- Edit [main/CMakeLists.txt](./main/CMakeLists.txt) to add/remove source files. + +- The [components/wolfssl/CMakeLists.txt](./components/wolfssl/CMakeLists.txt) typically does not need to be changed. + +- Optional [VisualGDB Project](./VisualGDB/wolfssl_template_IDF_v5.1_ESP32.vgdbproj) for Visual Studio using ESP32 and ESP-IDF v5.1. + +- Edit the project [CMakeLists.txt](./CMakeLists.txt) to optionally point this project's wolfSSL component source code at a different directory: + +``` +set(WOLFSSL_ROOT "~/workspace/wolfssl-other-source") +``` + + +## Getting Started: + +Here's an example using the command-line [idf.py](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/tools/idf-py.html). + +Edit your `WRK_IDF_PATH`to point to your ESP-IDF install directory. + +``` +WRK_IDF_PATH=/mnt/c/SysGCC/esp32/esp-idf/v5.1 + +echo "Run export.sh from ${WRK_IDF_PATH}" +. ${WRK_IDF_PATH}/export.sh + +# build the example: +idf.py build + +# flash the code onto the serial device at /dev/ttyS19 +idf.py flash -p /dev/ttyS19 -b 115200 + +# build, flash, and view UART output with one command: +idf.py flash -p /dev/ttyS19 -b 115200 monitor +``` + +Press `Ctrl+]` to exit `idf.py monitor`. See [additional monitor keyboard commands](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/tools/idf-monitor.html). + +## Other Examples: + +For examples, see: + +- [TLS Client](../wolfssl_client/README.md) +- [TLS Server](../wolfssl_server/README.md) +- [Benchmark](../wolfssl_benchmark/README.md) +- [Test](../wolfssl_test/README.md) +- [wolfssl-examples](https://github.com/wolfSSL/wolfssl-examples/tree/master/ESP32) +- [wolfssh-examples](https://github.com/wolfSSL/wolfssh-examples/tree/main/Espressif) + + + diff --git a/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/VisualGDB/wolfssh_echoserver_IDF_v5.1_ESP32.sln b/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/VisualGDB/wolfssh_echoserver_IDF_v5.1_ESP32.sln new file mode 100644 index 000000000..562cdb3f7 --- /dev/null +++ b/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/VisualGDB/wolfssh_echoserver_IDF_v5.1_ESP32.sln @@ -0,0 +1,37 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.7.34031.279 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{803FD0C6-D64E-4E16-9DC3-1DAEC859A3D2}") = "wolfssh_echoserver_IDF_v5.1_ESP32", "wolfssh_echoserver_IDF_v5.1_ESP32.vgdbproj", "{EADCC9AB-72B3-4B51-A838-593E5D80DDF7}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{510C1DEE-DFFB-4C38-864E-DCE7A172ABB7}" + ProjectSection(SolutionItems) = preProject + ..\..\..\..\..\..\..\wolfssl-gojimmypi\wolfssl\wolfcrypt\port\Espressif\esp32-crypt.h = ..\..\..\..\..\..\..\wolfssl-gojimmypi\wolfssl\wolfcrypt\port\Espressif\esp32-crypt.h + ..\README.md = ..\README.md + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|VisualGDB = Debug|VisualGDB + Release|VisualGDB = Release|VisualGDB + Tests (Debug)|VisualGDB = Tests (Debug)|VisualGDB + Tests (Release)|VisualGDB = Tests (Release)|VisualGDB + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {EADCC9AB-72B3-4B51-A838-593E5D80DDF7}.Debug|VisualGDB.ActiveCfg = Debug|VisualGDB + {EADCC9AB-72B3-4B51-A838-593E5D80DDF7}.Debug|VisualGDB.Build.0 = Debug|VisualGDB + {EADCC9AB-72B3-4B51-A838-593E5D80DDF7}.Release|VisualGDB.ActiveCfg = Release|VisualGDB + {EADCC9AB-72B3-4B51-A838-593E5D80DDF7}.Release|VisualGDB.Build.0 = Release|VisualGDB + {EADCC9AB-72B3-4B51-A838-593E5D80DDF7}.Tests (Debug)|VisualGDB.ActiveCfg = Tests (Debug)|VisualGDB + {EADCC9AB-72B3-4B51-A838-593E5D80DDF7}.Tests (Debug)|VisualGDB.Build.0 = Tests (Debug)|VisualGDB + {EADCC9AB-72B3-4B51-A838-593E5D80DDF7}.Tests (Release)|VisualGDB.ActiveCfg = Tests (Release)|VisualGDB + {EADCC9AB-72B3-4B51-A838-593E5D80DDF7}.Tests (Release)|VisualGDB.Build.0 = Tests (Release)|VisualGDB + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {C3DD3774-E396-475C-B78D-604D7CD9B732} + EndGlobalSection +EndGlobal diff --git a/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/VisualGDB/wolfssh_echoserver_IDF_v5.1_ESP32.vgdbproj b/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/VisualGDB/wolfssh_echoserver_IDF_v5.1_ESP32.vgdbproj new file mode 100644 index 000000000..2b846751e --- /dev/null +++ b/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/VisualGDB/wolfssh_echoserver_IDF_v5.1_ESP32.vgdbproj @@ -0,0 +1,269 @@ + + + + + + Unknown + + true + + 7bbd1486-d457-4e49-92ba-0cfc9d80849e + true + true + SourceDirs + + + + + + com.visualgdb.xtensa-esp32-elf + + 12.2.0 + 12.1 + 1 + + + .. + DEBUG + build/$(PlatformName)/$(ConfigurationName) + + false + $(ToolchainNinja) + $(BuildDir) + + + + false + $(SYSPROGS_CMAKE_PATH) + + + true + false + false + Ninja + false + RemoveBuildDirectory + false + + + true + true + true + false + true + false + true + HideOuterProjectTargets + true + false + true + + + true + eadcc9ab-72b3-4b51-a838-593e5d80ddf7 + + Upper + HeaderDirectoryAndSubdirectories + true + + + release/v5.1 + esp-idf/v5.1 + ESPIDF + + COM19 + false + false + ESP32 + + + + + + + + + + + + + + + Default + + + + COM19 + + 115200 + 8 + None + One + None + + + 0 + false + true + false + ASCII + + + 255 + 0 + 0 + 0 + + + 255 + 169 + 169 + 169 + + + 255 + 211 + 211 + 211 + + + 255 + 144 + 238 + 144 + + + 255 + 169 + 169 + 169 + + + + 16 + true + true + true + true + 0 + + LF + false + false + false + + + + true + + + + + Unknown + + true + true + true + + + + false + + + + + Debug + + + + Release + + + + + + + + + false + false + false + false + false + false + false + false + false + + false + false + false + false + false + false + true + false + None + false + false + app_main + true + false + false + true + 0 + false + 0 + true + false + + + openocd + + -f interface/ftdi/tigard.cfg -c "adapter_khz 15000" -f target/esp32.cfg + + + + false + + 131072 + Enabled + + set remotetimeout 60 + target remote :$$SYS:GDB_PORT$$ + mon gdb_breakpoint_override hard + mon reset halt + load + + false + 0 + 0 + false + + 5000 + 1 + true + + size2MB + freq40M + DIO + + true + + + true + Disabled + 0 + false + false + true + false + false + + _estack + 0 + false + + true + + \ No newline at end of file diff --git a/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/components/wolfssh/CMakeLists.txt b/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/components/wolfssh/CMakeLists.txt new file mode 100644 index 000000000..c3e5d37ab --- /dev/null +++ b/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/components/wolfssh/CMakeLists.txt @@ -0,0 +1,545 @@ +# [wolfSSL Project]/components/wolfssh/CMakeLists.txt +# +# Copyright (C) 2006-2023 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 2 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 this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA +# +# cmake for WOLFSSH Espressif projects v5.6.6 r1 +# +# See https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/build-system.html +# + +cmake_minimum_required(VERSION 3.16) +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DWOLFSSH_USER_SETTINGS") + +# find the user name to search for possible "wolfssh-username" +message(STATUS "USERNAME = $ENV{USERNAME}") +if( "$ENV{USER}" STREQUAL "" ) # the bash user + if( "$ENV{USERNAME}" STREQUAL "" ) # the Windows user + message(STATUS "could not find USER or USERNAME") + else() + # the bash user is not blank, so we'll use it. + set(THIS_USER "$ENV{USERNAME}") + endif() +else() + # the bash user is not blank, so we'll use it. + set(THIS_USER "$ENV{USER}") +endif() +message(STATUS "THIS_USER = ${THIS_USER}") + +# Attention! +# +# When editing component CMake files, consider the following : +# +# NO Managed Componenets: Normal stand-alone app, "as cloned" from github. +# There's no notion of staging names (e.g. mywolfssh) regardless of environment settings. +# All of the component source is locall. See settings such s WOLFSSL_ROOT=[your path] +# +# Partially Managed Components. This one is tricky. When publishing a component with examples, +# those examples will have a chicken-and-egg problem: the required component is not yet published. +# Adding to the complexity is the notion of staging components, that are purposely prefixed with +# "my" (e.g. mywolfssh) to distinguish from production, live components (e.g. wolfssh) +# +# Partially Managed Component Examples are typically only encountered by the component publisher +# and only at publish time, such as when performing the pre-publish build check. +# +# A partially managed component may also be manually created, when adding a managed component to +# and existing project. For example: +# +# idf.py add-dependency "wolfssl/wolfssh^1.4.15-stable" +# +# Fully Managaged Componenets. This is the typical example as created from the Component Registry: +# For example: +# +# idf.py create-project-from-example "wolfssl/wolfssh^1.4.15-stable:wolfssh_server" +# +# In all cases, keep in mind that components other than wolfssl will depend on the wolfssl component. +# +message(STATUS "CMAKE_CURRENT_LIST_DIR = ${CMAKE_CURRENT_LIST_DIR}") + +get_filename_component(THIS_DIR "${CMAKE_CURRENT_LIST_DIR}" ABSOLUTE) +message(STATUS "THIS_DIR = ${THIS_DIR}") + +# The root of the project is two directories up from here. (we are typically in [project name]components/mywolfssh) +get_filename_component(PROJECT_ROOT "${THIS_DIR}" DIRECTORY) # Up one directory from here is "components" +get_filename_component(PROJECT_ROOT "${PROJECT_ROOT}" DIRECTORY) # up one more directory should be the root of our project +message(STATUS "PROJECT_ROOT = ${PROJECT_ROOT}") + + +# Component naming is only adjusted when using Managed Components, and only when using staging site. +if( "$ENV{IDF_COMPONENT_REGISTRY_URL}" STREQUAL "https://components-staging.espressif.com" ) + # TODO: Is checking these two variables really the best way to detect an active Component Manager? + message(STATUS "component_manager_interface_version = ${component_manager_interface_version}") + message(STATUS "managed_components = ${managed_components}") + message(STATUS "Checking if wolfssl is in ${PROJECT_ROOT}/managed_components/${THIS_USER}__mywolfssl") + + if(EXISTS "${PROJECT_ROOT}/managed_components/${THIS_USER}__mywolfssl/CMakeLists.txt") + message(STATUS "Found user-specific, managed, staging component. The wolfssl component will be named mywolfssl.") + set(WOLFSSL_COMPONENT_NAME "mywolfssl") + elseif( ("${managed_components}" STREQUAL "") AND ("${component_manager_interface_version}" STREQUAL "") ) + # We've found a staging component, but did not detect the component manager + message(STATUS "No component manager interface component wolfssl ${CMAKE_HOME_DIRECTORY}") + set(WOLFSSL_COMPONENT_NAME "wolfssl") + else() + message(STATUS "else mywolfssl") + set(WOLFSSL_COMPONENT_NAME "mywolfssl") + endif() +elseif(EXISTS "${CMAKE_HOME_DIRECTORY}/managed_components/${THIS_USER}__mywolfssl/CMakeLists.txt") + message(STATUS "Found managed_components mywolfssl") + set(WOLFSSL_COMPONENT_NAME "mywolfssl") +else() + message(STATUS "Not staging environment, no managed_components wolfssl") + set(WOLFSSL_COMPONENT_NAME "wolfssl") +endif() + +set(COMPONENT_REQUIRES lwip "${WOLFSSL_COMPONENT_NAME}") + +# function: IS_WOLFSSH_SOURCE +# parameter: DIRECTORY_PARAMETER - the directory to test +# output: RESULT = contains contents of DIRECTORY_PARAMETER for wolfssh directory, otherwise blank. +function(IS_WOLFSSH_SOURCE DIRECTORY_PARAMETER RESULT) + if (EXISTS "${DIRECTORY_PARAMETER}/wolfssh/ssh.h") + if (EXISTS "${DIRECTORY_PARAMETER}/wolfssh") + message(STATUS "1") + endif() + if (EXISTS "${DIRECTORY_PARAMETER}") + message(STATUS "2") + endif() + if (EXISTS "${DIRECTORY_PARAMETER}/src") + message(STATUS "3") + endif() + set(${RESULT} "${DIRECTORY_PARAMETER}" PARENT_SCOPE) + else() + set(${RESULT} "" PARENT_SCOPE) + endif() +endfunction() + +# function: FIND_WOLFSSH_DIRECTORY +# parameter: OUTPUT_FOUND_WOLFSSH_DIRECTORY contains root of source code, otherwise blank +# +function(FIND_WOLFSSH_DIRECTORY OUTPUT_FOUND_WOLFSSH_DIRECTORY) + message(STATUS "Starting FIND_WOLFSSH_DIRECTORY") + set(CURRENT_SEARCH_DIR "$ENV{WOLFSSH_ROOT}") + if( "${CURRENT_SEARCH_DIR}" STREQUAL "" ) + message(STATUS "The WOLFSSH_ROOT environment variable is not set. Searching...") + else() + # There's a non-blank WOLFSSH_ROOT environment variable. Is it a valid wolfssh directory? + get_filename_component(CURRENT_SEARCH_DIR "$ENV{WOLFSSH_ROOT}" ABSOLUTE) + IS_WOLFSSH_SOURCE("${CURRENT_SEARCH_DIR}" FOUND_WOLFSSH) + if("${FOUND_WOLFSSH}") + message(STATUS "Found WOLFSSH_ROOT via Environment Variable:") + else() + message(FATAL_ERROR "WOLFSSH_ROOT Environment Variable defined, but path not found: $ENV{WOLFSSH_ROOT}") + message(STATUS "Exit CMake") + endif() + endif() + + # we'll start in the THIS_CMAKE_CURRENT_SOURCE_DIR, typically [something]/projectname/components/WOLFSSH + message(STATUS "THIS_CMAKE_CURRENT_SOURCE_DIR = ${THIS_CMAKE_CURRENT_SOURCE_DIR}") + get_filename_component(CURRENT_SEARCH_DIR "${THIS_CMAKE_CURRENT_SOURCE_DIR}" ABSOLUTE) + message(STATUS "CURRENT_SEARCH_DIR = ${CURRENT_SEARCH_DIR}") + string(LENGTH ${CURRENT_SEARCH_DIR} CURRENT_SEARCH_DIR_LENGTH) + + # loop through all the parents, looking for wolfssh + while(NOT CURRENT_SEARCH_DIR STREQUAL "/" AND NOT CURRENT_SEARCH_DIR STREQUAL "" ) + string(LENGTH ${CURRENT_SEARCH_DIR} CURRENT_SEARCH_DIR_LENGTH) + # wolfssh may simply be in a parent directory, such as for local examples in WOLFSSH repo + IS_WOLFSSH_SOURCE("${CURRENT_SEARCH_DIR}" FOUND_WOLFSSH) + if( FOUND_WOLFSSH ) + message(STATUS "Found wolfssh in CURRENT_SEARCH_DIR = ${CURRENT_SEARCH_DIR}") + set(${OUTPUT_FOUND_WOLFSSH_DIRECTORY} ${CURRENT_SEARCH_DIR} PARENT_SCOPE) + return() + endif() + + if( THIS_USER ) + # Check for "wolfssh-[username]" subdirectory as we recurse up the directory tree + set(CURRENT_SEARCH_DIR_ALT "${CURRENT_SEARCH_DIR}/wolfssh-${THIS_USER}") + message(STATUS "Looking in ${CURRENT_SEARCH_DIR}") + + #if(EXISTS ${CURRENT_SEARCH_DIR_ALT} AND IS_DIRECTORY ${CURRENT_SEARCH_DIR_ALT} AND EXISTS "${CURRENT_SEARCH_DIR_ALT}/wolfcrypt/src") + IS_WOLFSSH_SOURCE("${CURRENT_SEARCH_DIR_ALT}" FOUND_WOLFSSH ) + if ( FOUND_WOLFSSH ) + message(STATUS "Found wolfssh in user-suffix CURRENT_SEARCH_DIR_ALT = ${CURRENT_SEARCH_DIR_ALT}") + set(${OUTPUT_FOUND_WOLFSSH_DIRECTORY} ${CURRENT_SEARCH_DIR_ALT} PARENT_SCOPE) + return() + endif() + endif() + + # Next check for no user suffix "WOLFSSH" subdirectory as we recurse up the directory tree + set(CURRENT_SEARCH_DIR_ALT ${CURRENT_SEARCH_DIR}/wolfssh) + # if(EXISTS ${CURRENT_SEARCH_DIR} AND IS_DIRECTORY ${CURRENT_SEARCH_DIR} AND EXISTS "${CURRENT_SEARCH_DIR}/wolfcrypt/src") + IS_WOLFSSH_SOURCE("${CURRENT_SEARCH_DIR_ALT}" FOUND_WOLFSSH ) + if ( FOUND_WOLFSSH ) + message(STATUS "Found wolfssh in CURRENT_SEARCH_DIR = ${CURRENT_SEARCH_DIR}") + set(${OUTPUT_FOUND_WOLFSSH_DIRECTORY} ${CURRENT_SEARCH_DIR} PARENT_SCOPE) + return() + endif() + + # Move up one directory level + set(PRIOR_SEARCH_DIR "${CURRENT_SEARCH_DIR}") + get_filename_component(CURRENT_SEARCH_DIR "${CURRENT_SEARCH_DIR}" DIRECTORY) + message(STATUS "Next CURRENT_SEARCH_DIR = ${CURRENT_SEARCH_DIR}") + if( "${PRIOR_SEARCH_DIR}" STREQUAL "${CURRENT_SEARCH_DIR}" ) + # when the search directory is empty, we'll give up + set(CURRENT_SEARCH_DIR "") + endif() + endwhile() + + # If not found, set the output variable to empty before exiting + set(${OUTPUT_FOUND_WOLFSSH_DIRECTORY} "" PARENT_SCOPE) +endfunction() + +# COMPONENT_NAME = wolfssh +# The component name is the directory name. "No feature to change this". +# See https://github.com/espressif/esp-idf/issues/8978#issuecomment-1129892685 + +# set the root of WOLFSSH in top-level project CMakelists.txt: +# set(WOLFSSH_ROOT "C:/some path/with/spaces") +# set(WOLFSSH_ROOT "c:/workspace/WOLFSSH-[username]") +# set(WOLFSSH_ROOT "/mnt/c/some path/with/spaces") +# or use this logic to assign value from Environment Variable WOLFSSH_ROOT, +# or assume this is an example 7 subdirectories below: + +# We are typically in [root]/IDE/Espressif/ESP-IDF/examples/WOLFSSH_test/components/WOLFSSH +# The root of WOLFSSH is 7 directories up from here: + +if(CMAKE_BUILD_EARLY_EXPANSION) + message(STATUS "WOLFSSH component CMAKE_BUILD_EARLY_EXPANSION:") + idf_component_register( + REQUIRES "${COMPONENT_REQUIRES}" + PRIV_REQUIRES + esp_timer + driver + "${WOLFSSL_COMPONENT_NAME}" # either wolfssl or mywolfssl as a staging component + ) + +else() + # not CMAKE_BUILD_EARLY_EXPANSION + message(STATUS "************************************************************************************************") + message(STATUS "wolfssh component config:") + message(STATUS "************************************************************************************************") + FIND_WOLFSSH_DIRECTORY(WOLFSSH_ROOT) + + set(WOLFSSH_ROOT "${WOLFSSH_ROOT}" CACHE STRING "WOLFSSH_ROOT") + if(WOLFSSH_ROOT) + message(STATUS "Found wolfssh directory at: ${WOLFSSH_ROOT}") + else() + message(STATUS "wolfssh directory not found.") + # Abort. We need wolfmqtt _somewhere_. + message(FATAL_ERROR "Could not find wolfssh in ${WOLFSSH_ROOT}.\n" + "Try setting WOLFSSH_ROOT environment variable or git clone.") + endif() + + + # After all the logic above, does our WOLFSSH_ROOT actually exist? + if( EXISTS "${WOLFSSH_ROOT}" ) + message(STATUS "WOLFSSH_ROOT = ${WOLFSSH_ROOT}") + else() + # Abort. We need WOLFSSH _somewhere_. + message(FATAL_ERROR "Could not find WOLFSSH in ${WOLFSSH_ROOT}. Try setting environment variable or git clone.") + endif() + + + set(INCLUDE_PATH ${WOLFSSH_ROOT}) + + set(COMPONENT_SRCDIRS + "\"${WOLFSSH_ROOT}/src/\"" + ) # COMPONENT_SRCDIRS + message(STATUS "This COMPONENT_SRCDIRS = ${COMPONENT_SRCDIRS}") + + set(WOLFSSH_PROJECT_DIR "${CMAKE_HOME_DIRECTORY}/components/wolfssh") + + # Espressif may take several passes through this makefile. Check to see if we found IDF + string(COMPARE EQUAL "${PROJECT_SOURCE_DIR}" "" WOLFSSH_FOUND_IDF) + + message(STATUS "IDF_PATH = $ENV{IDF_PATH}") + message(STATUS "PROJECT_SOURCE_DIR = ${PROJECT_SOURCE_DIR}") + message(STATUS "EXCLUDE_ASM = ${EXCLUDE_ASM}") + + # + # Check to see if there's both a local copy and EDP-IDF copy of the WOLFSSH and/or wolfssh components. + # + if( EXISTS "${WOLFSSH_PROJECT_DIR}" AND EXISTS "$ENV{IDF_PATH}/components/WOLFSSH/" ) + # + # WOLFSSH found in both ESP-IDF and local project - needs to be resolved by user + # + message(STATUS "") + message(STATUS "**************************************************************************************") + message(STATUS "") + message(STATUS "Error: Found components/WOLFSSH in both local project and IDF_PATH") + message(STATUS "") + message(STATUS "To proceed: ") + message(STATUS "") + message(STATUS "Remove either the local project component: ${WOLFSSH_PROJECT_DIR} ") + message(STATUS "or the Espressif shared component installed at: $ENV{IDF_PATH}/components/WOLFSSH/ ") + message(STATUS "") + message(FATAL_ERROR "Please use WOLFSSH in either local project or Espressif components, but not both.") + message(STATUS "") + message(STATUS "**************************************************************************************") + message(STATUS "") + + # Optional: if you change the above FATAL_ERROR to STATUS you can warn at runtime with this macro definition: + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DWOLFSSH_MULTI_INSTALL_WARNING") + + else() + if( EXISTS "$ENV{IDF_PATH}/components/WOLFSSH/" ) + # + # WOLFSSH found in ESP-IDF components and is assumed to be already configured in user_settings.h via setup. + # + message(STATUS "") + message(STATUS "Using components/WOLFSSH in IDF_PATH = $ENV{IDF_PATH}") + message(STATUS "") + else() + # + # WOLFSSH is not an ESP-IDF component. + # We need to now determine if it is local and if so if it is part of the WOLFSSH repo, + # or if WOLFSSH is simply installed as a local component. + # + + if( EXISTS "${WOLFSSH_PROJECT_DIR}" ) + # + # WOLFSSH found in local project. + # + if( EXISTS "${WOLFSSH_PROJECT_DIR}/wolfcrypt/" ) + message(STATUS "") + message(STATUS "Using installed project ./components/WOLFSSH in CMAKE_HOME_DIRECTORY = ${CMAKE_HOME_DIRECTORY}") + message(STATUS "") + # + # Note we already checked above and confirmed there's not another WOLFSSH installed in the ESP-IDF components. + # + # We won't do anything else here, as it will be assumed the original install completed successfully. + # + else() # full WOLFSSH not installed in local project + # + # This is the developer repo mode. WOLFSSH will be assumed to be not installed to ESP-IDF nor local project + # In this configuration, we are likely running a WOLFSSH example found directly in the repo. + # + message(STATUS "") + message(STATUS "Using developer repo ./components/WOLFSSH in CMAKE_HOME_DIRECTORY = ${CMAKE_HOME_DIRECTORY}") + message(STATUS "") + + message(STATUS "************************************************************************************************") + # When in developer mode, we are typically running WOLFSSH examples such as benchmark or test directories. + # However, the as-cloned or distributed WOLFSSH does not have the ./include/ directory, so we'll add it as needed. + # + # first check if there's a [root]/include/user_settings.h + if( EXISTS "${WOLFSSH_ROOT}/include/user_settings.h" ) + message(FATAL_ERROR "Found stray WOLFSSH user_settings.h in " + "${WOLFSSH_ROOT}/include/user_settings.h " + " (please move it to ${WOLFSSH_PROJECT_DIR}/include/user_settings.h )") + else() + # we won't overwrite an existing user settings file, just note that we already have one: + if( EXISTS "${WOLFSSH_PROJECT_DIR}/include/user_settings.h" ) + message(STATUS "Using existing WOLFSSH user_settings.h in " + "${WOLFSSH_PROJECT_DIR}/include/user_settings.h") + else() + message(STATUS "Installing WOLFSSH user_settings.h to " + "${WOLFSSH_PROJECT_DIR}/include/user_settings.h") + # file(COPY "${WOLFSSH_ROOT}/IDE/Espressif/ESP-IDF/user_settings.h" + # DESTINATION "${CMAKE_HOME_DIRECTORY}/WOLFSSH/include/") + endif() + endif() # user_settings.h + + message(STATUS "************************************************************************************************") + message(STATUS "") + endif() + + else() + # we did not find a ./components/WOLFSSH/include/ directory from this pass of cmake. + if($WOLFSSH_FOUND_IDF) + message(STATUS "") + message(STATUS "WARNING: WOLFSSH not found.") + message(STATUS "") + else() + # probably needs to be re-parsed by Espressif + message(STATUS "WOLFSSH found IDF. Project Source:${PROJECT_SOURCE_DIR}") + endif() # else we have not found ESP-IDF yet + endif() # else not a local WOLFSSH component + + endif() #else not an ESP-IDF component + endif() # else not local copy and EDP-IDF WOLFSSH + + + # 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/FreeRTOS-Kernel/include/freertos") + + string(REPLACE "\\" "/" WOLFSSH_ROOT ${WOLFSSH_ROOT}) + + if(IS_DIRECTORY "${RTOS_IDF_PATH}") + message(STATUS "Found current RTOS path: ${RTOS_IDF_PATH}") + else() + # ESP-IDF prior version 4.4x has a different RTOS directory structure + string(REPLACE "\\" "/" RTOS_IDF_PATH "$ENV{IDF_PATH}/components/freertos/include/freertos") + if(IS_DIRECTORY "${RTOS_IDF_PATH}") + message(STATUS "Found legacy RTOS path: ${RTOS_IDF_PATH}") + else() + message(STATUS "Could not find RTOS path") + endif() + endif() + + + set(COMPONENT_ADD_INCLUDEDIRS + # "./include" # not used! See wolfSSL include/user_settings.h + "\"${WOLFSSH_ROOT}/\"" + "\"${WOLFSSH_ROOT}/wolfssh/\"" + "\"${RTOS_IDF_PATH}/\"" + ) + + + if(IS_DIRECTORY ${IDF_PATH}/components/cryptoauthlib) + list(APPEND COMPONENT_ADD_INCLUDEDIRS "../cryptoauthlib/lib") + endif() + + list(APPEND COMPONENT_ADD_INCLUDEDIRS "\"${WOLFSSH_ROOT}/wolfssh/\"") + + + + set(COMPONENT_SRCEXCLUDE + # wolfSSH + # TODO: we likely need to check #if !defined(WOLFSSH_MISC_INCLUDED) && !defined(NO_INLINE) && !defined(WOLFSSH_IGNORE_FILE_WARN) + # here in cmake if we actually want to always exclude wolfssh misc.c file. (see source; ok for demo) + "\"${WOLFSSH_ROOT}/src/misc.c\"" # misc.c does not need to be compiled when using inline (NO_INLINE not defined)) + ) + + spaces2list(COMPONENT_REQUIRES) + + separate_arguments(COMPONENT_SRCDIRS NATIVE_COMMAND "${COMPONENT_SRCDIRS}") + separate_arguments(COMPONENT_SRCEXCLUDE NATIVE_COMMAND "${COMPONENT_SRCEXCLUDE}") + separate_arguments(COMPONENT_ADD_INCLUDEDIRS NATIVE_COMMAND "${COMPONENT_ADD_INCLUDEDIRS}") + + # + # See https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/build-system.html#example-component-requirements + # + message(STATUS "COMPONENT_SRCDIRS = ${COMPONENT_SRCDIRS}") + message(STATUS "COMPONENT_ADD_INCLUDEDIRS = ${COMPONENT_ADD_INCLUDEDIRS}") + message(STATUS "COMPONENT_REQUIRES = ${COMPONENT_REQUIRES}") + message(STATUS "COMPONENT_SRCEXCLUDE = ${COMPONENT_SRCEXCLUDE}") + + # + # see https://docs.espressif.com/projects/esp-idf/en/stable/esp32/migration-guides/release-5.x/build-system.html?highlight=space%20path + # + set(EXTRA_COMPONENT_DIRS "${COMPONENT_SRCDIRS}") + idf_component_register( + SRC_DIRS "${COMPONENT_SRCDIRS}" + INCLUDE_DIRS "${COMPONENT_ADD_INCLUDEDIRS}" + REQUIRES "${COMPONENT_REQUIRES}" + EXCLUDE_SRCS "${COMPONENT_SRCEXCLUDE}" + PRIV_REQUIRES + esp_timer + driver + "${WOLFSSL_COMPONENT_NAME}" # either wolfssl or mywolfssl as a staging component + ) + # some optional diagnostics + if (1) + get_cmake_property(_variableNames VARIABLES) + list (SORT _variableNames) + message(STATUS "") + message(STATUS "ALL VARIABLES BEGIN") + message(STATUS "") + foreach (_variableName ${_variableNames}) + message(STATUS "${_variableName}=${${_variableName}}") + endforeach() + message(STATUS "") + message(STATUS "ALL VARIABLES END") + message(STATUS "") + endif() + + # target_sources(WOLFSSH PRIVATE "\"${WOLFSSH_ROOT}/WOLFSSH/\"" "\"${WOLFSSH_ROOT}/WOLFSSH/wolfcrypt\"") +endif() # CMAKE_BUILD_EARLY_EXPANSION + + + +# check to see if there's both a local copy and EDP-IDF copy of the WOLFSSH components +if( EXISTS "${WOLFSSH_PROJECT_DIR}" AND EXISTS "$ENV{IDF_PATH}/components/WOLFSSH/" ) + message(STATUS "") + message(STATUS "") + message(STATUS "********************************************************************") + message(STATUS "WARNING: Found components/WOLFSSH in both local project and IDF_PATH") + message(STATUS "********************************************************************") + message(STATUS "") +endif() +# end multiple component check + + +# +# LIBWOLFSSH_SAVE_INFO(VAR_OUPUT THIS_VAR VAR_RESULT) +# +# Save the THIS_VAR as a string in a macro called VAR_OUPUT +# +# VAR_OUPUT: the name of the macro to define +# THIS_VAR: the OUTPUT_VARIABLE result from a execute_process() +# VAR_RESULT: the RESULT_VARIABLE from a execute_process(); "0" if successful. +# +function ( LIBWOLFSSH_SAVE_INFO VAR_OUPUT THIS_VAR VAR_RESULT ) + # is the RESULT_VARIABLE output value 0? If so, IS_VALID_VALUE is true. + string(COMPARE EQUAL "${VAR_RESULT}" "0" IS_VALID_VALUE) + + # if we had a successful operation, save the THIS_VAR in VAR_OUPUT + if(${IS_VALID_VALUE}) + # strip newline chars in THIS_VAR parameter and save in VAR_VALUE + string(REPLACE "\n" "" VAR_VALUE ${THIS_VAR}) + + # we'll could percolate the value to the parent for possible later use + # set(${VAR_OUPUT} ${VAR_VALUE} PARENT_SCOPE) + + # but we're only using it here in this function + set(${VAR_OUPUT} ${VAR_VALUE}) + + # we'll print what we found to the console + message(STATUS "Found ${VAR_OUPUT}=${VAR_VALUE}") + + # the interesting part is defining the VAR_OUPUT name a value to use in the app + add_definitions(-D${VAR_OUPUT}=\"${VAR_VALUE}\") + else() + # if we get here, check the execute_process command and parameters. + message(STATUS "LIBWOLFSSH_SAVE_INFO encountered a non-zero VAR_RESULT") + set(${VAR_OUPUT} "Unknown") + endif() +endfunction() # LIBWOLFSSH_SAVE_INFO + +# create some programmatic #define values that will be used by ShowExtendedSystemInfo(). +# see wolfcrypt\src\port\Espressif\esp32_utl.c +if(NOT CMAKE_BUILD_EARLY_EXPANSION) + set (git_cmd "git") + message(STATUS "Adding macro definitions:") + + # LIBWOLFSSH_VERSION_GIT_ORIGIN: git config --get remote.origin.url + execute_process(WORKING_DIRECTORY ${WOLFSSH_ROOT} COMMAND ${git_cmd} "config" "--get" "remote.origin.url" OUTPUT_VARIABLE TMP_OUT RESULT_VARIABLE TMP_RES ERROR_QUIET ) + LIBWOLFSSH_SAVE_INFO(LIBWOLFSSH_VERSION_GIT_ORIGIN "${TMP_OUT}" "${TMP_RES}") + + # LIBWOLFSSH_VERSION_GIT_BRANCH: git rev-parse --abbrev-ref HEAD + execute_process(WORKING_DIRECTORY ${WOLFSSH_ROOT} COMMAND ${git_cmd} "rev-parse" "--abbrev-ref" "HEAD" OUTPUT_VARIABLE TMP_OUT RESULT_VARIABLE TMP_RES ERROR_QUIET ) + LIBWOLFSSH_SAVE_INFO(LIBWOLFSSH_VERSION_GIT_BRANCH "${TMP_OUT}" "${TMP_RES}") + + # LIBWOLFSSH_VERSION_GIT_HASH: git rev-parse HEAD + execute_process(WORKING_DIRECTORY ${WOLFSSH_ROOT} COMMAND ${git_cmd} "rev-parse" "HEAD" OUTPUT_VARIABLE TMP_OUT RESULT_VARIABLE TMP_RES ERROR_QUIET ) + LIBWOLFSSH_SAVE_INFO(LIBWOLFSSH_VERSION_GIT_HASH "${TMP_OUT}" "${TMP_RES}") + + # LIBWOLFSSH_VERSION_GIT_SHORT_HASH: git rev-parse --short HEAD + execute_process(WORKING_DIRECTORY ${WOLFSSH_ROOT} COMMAND ${git_cmd} "rev-parse" "--short" "HEAD" OUTPUT_VARIABLE TMP_OUT RESULT_VARIABLE TMP_RES ERROR_QUIET ) + LIBWOLFSSH_SAVE_INFO(LIBWOLFSSH_VERSION_GIT_SHORT_HASH "${TMP_OUT}" "${TMP_RES}") + + # LIBWOLFSSH_VERSION_GIT_HASH_DATE git show --no-patch --no-notes --pretty=\'\%cd\' + execute_process(WORKING_DIRECTORY ${WOLFSSH_ROOT} COMMAND ${git_cmd} "show" "--no-patch" "--no-notes" "--pretty=\'\%cd\'" OUTPUT_VARIABLE TMP_OUT RESULT_VARIABLE TMP_RES ) + LIBWOLFSSH_SAVE_INFO(LIBWOLFSSH_VERSION_GIT_HASH_DATE "${TMP_OUT}" "${TMP_RES}") + + message(STATUS "************************************************************************************************") + message(STATUS "WOLFSSH component config complete!") + message(STATUS "************************************************************************************************") +endif() diff --git a/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/components/wolfssl/CMakeLists.txt b/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/components/wolfssl/CMakeLists.txt new file mode 100644 index 000000000..d58704b84 --- /dev/null +++ b/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/components/wolfssl/CMakeLists.txt @@ -0,0 +1,676 @@ +# +# Copyright (C) 2006-2023 wolfSSL Inc. +# +# This file is part of wolfSSL. +# +# wolfSSL 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 2 of the License, or +# (at your option) any later version. +# +# wolfSSL 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 this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA +# +# cmake for wolfssl Espressif projects +# +# Version 5.6.4.016 for improved manual setting of WOLFSSL_ROOT + ESP8266 support; optional esp-timer / driver components +# +# See https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/build-system.html +# + +cmake_minimum_required(VERSION 3.16) + +set(VERBOSE_COMPONENT_MESSAGES 1) + +# The scope of this CMAKE_C_FLAGS is just this component: +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DWOLFSSL_USER_SETTINGS") + +set(CMAKE_CURRENT_SOURCE_DIR ".") +# set(COMPONENT_REQUIRES lwip) # we typically don't need lwip directly in wolfssl component + +# Optionally set your source to wolfSSL in your project CMakeLists.txt like this: +# set(WOLFSSL_ROOT "c:/test/blogtest/wolfssl" ) + +if ( "${WOLFSSL_ROOT}" STREQUAL "") + set(WOLFSSL_ROOT "$ENV{WOLFSSL_ROOT}" ) +endif() +# Optional compiler definitions to help with system name detection (typically printed by app diagnostics) +if(VERBOSE_COMPONENT_MESSAGES) + if(WIN32) + # Windows-specific configuration here + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DWOLFSSL_CMAKE_SYSTEM_NAME_WINDOWS") + message("Detected Windows") + endif() + if(CMAKE_HOST_UNIX) + message("Detected UNIX") + endif() + if(APPLE) + message("Detected APPLE") + endif() + if(CMAKE_HOST_UNIX AND (NOT APPLE) AND EXISTS "/proc/sys/fs/binfmt_misc/WSLInterop") + # Windows-specific configuration here + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DWOLFSSL_CMAKE_SYSTEM_NAME_WSL") + message("Detected WSL") + endif() + if(CMAKE_HOST_UNIX AND (NOT APPLE) AND (NOT WIN32)) + # Windows-specific configuration here + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DWOLFSSL_CMAKE_SYSTEM_NAME_LINUX") + message("Detected Linux") + endif() + if(APPLE) + # Windows-specific configuration here + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DWOLFSSL_CMAKE_SYSTEM_NAME_APPLE") + message("Detected Apple") + endif() +endif() # End optional WOLFSSL_CMAKE_SYSTEM_NAME + +message(STATUS "CONFIG_TARGET_PLATFORM = ${CONFIG_TARGET_PLATFORM}") + +# Check that there are not conflicting wolfSSL components +# The ESP Registry Component will be in ./managed_components/wolfssl__wolfssl +# The local component wolfSSL directory will be in ./components/wolfssl +if( EXISTS "${CMAKE_HOME_DIRECTORY}/managed_components/wolfssl__wolfssl" AND EXISTS "${CMAKE_HOME_DIRECTORY}/components/wolfssl" ) + # These exclude statements don't seem to be honored by the $ENV{IDF_PATH}/tools/cmake/project.cmake' + # add_subdirectory("${CMAKE_HOME_DIRECTORY}/managed_components/wolfssl__wolfssl" EXCLUDE_FROM_ALL) + # add_subdirectory("${CMAKE_HOME_DIRECTORY}/managed_components/wolfssl__wolfssl/include" EXCLUDE_FROM_ALL) + # So we'll error out and let the user decide how to proceed: + message(WARNING "\nFound wolfSSL components in\n" + "./managed_components/wolfssl__wolfssl\n" + "and\n" + "./components/wolfssl\n" + "in project directory: \n" + "${CMAKE_HOME_DIRECTORY}") + message(FATAL_ERROR "\nPlease use either the ESP Registry Managed Component or the wolfSSL component directory but not both.\n" + "If removing the ./managed_components/wolfssl__wolfssl directory, remember to also remove " + "or rename the idf_component.yml file typically found in ./main/") +else() + message(STATUS "No conflicting wolfSSL components found.") +endif() + + +# Don't include lwip requirement for benchmark and test apps. +if( ("${CMAKE_PROJECT_NAME}" STREQUAL "wolfssl_benchmark") OR ("${CMAKE_PROJECT_NAME}" STREQUAL "wolfssl_test") ) + message(STATUS "Not including lwip for ${CMAKE_PROJECT_NAME}") +else() + # benchmark and test do not need wifi, everything else probably does: + set(COMPONENT_REQUIRES lwip) # we typically don't need lwip directly in wolfssl component +endif() + +# find the user name to search for possible "wolfssl-username" +message(STATUS "USERNAME = $ENV{USERNAME}") +if( "$ENV{USER}" STREQUAL "" ) # the bash user + if( "$ENV{USERNAME}" STREQUAL "" ) # the Windows user + message(STATUS "could not find USER or USERNAME") + else() + # the bash user is not blank, so we'll use it. + set(THIS_USER "$ENV{USERNAME}") + endif() +else() + # the bash user is not blank, so we'll use it. + set(THIS_USER "$ENV{USER}") +endif() +message(STATUS "THIS_USER = ${THIS_USER}") + + +# COMPONENT_NAME = wolfssl +# The component name is the directory name. "No feature to change this". +# See https://github.com/espressif/esp-idf/issues/8978#issuecomment-1129892685 + +# set the root of wolfSSL in top-level project CMakelists.txt: +# set(WOLFSSL_ROOT "C:/some path/with/spaces") +# set(WOLFSSL_ROOT "c:/workspace/wolfssl-[username]") +# set(WOLFSSL_ROOT "/mnt/c/some path/with/spaces") +# or use this logic to assign value from Environment Variable WOLFSSL_ROOT, +# or assume this is an example 7 subdirectories below: + +# We are typically in [root]/IDE/Espressif/ESP-IDF/examples/wolfssl_test/components/wolfssl +# The root of wolfSSL is 7 directories up from here: + +# function: IS_WOLFSSL_SOURCE +# parameter: DIRECTORY_PARAMETER - the directory to test +# output: RESULT = contains contents of DIRECTORY_PARAMETER for wolfssl directory, otherwise blank. +function(IS_WOLFSSL_SOURCE DIRECTORY_PARAMETER RESULT) + if (EXISTS "${DIRECTORY_PARAMETER}/wolfcrypt/src") + set(${RESULT} "${DIRECTORY_PARAMETER}" PARENT_SCOPE) + else() + set(${RESULT} "" PARENT_SCOPE) + endif() +endfunction() + +# ********************************************************************************************* +# function: FIND_WOLFSSL_DIRECTORY +# parameter: OUTPUT_FOUND_WOLFSSL_DIRECTORY contains root of source code, otherwise blank +# +# Example usage: +# FIND_WOLFSSL_DIRECTORY(WOLFSSL_ROOT) +# ********************************************************************************************* +function(FIND_WOLFSSL_DIRECTORY OUTPUT_FOUND_WOLFSSL_DIRECTORY) + message(STATUS "Starting FIND_WOLFSSL_DIRECTORY: ${${OUTPUT_FOUND_WOLFSSL_DIRECTORY}}") + + if ( "${${OUTPUT_FOUND_WOLFSSL_DIRECTORY}}" STREQUAL "" ) + set(CURRENT_SEARCH_DIR "$ENV{WOLFSSL_ROOT}") + if( "${CURRENT_SEARCH_DIR}" STREQUAL "" ) + message(STATUS "The WOLFSSL_ROOT environment variable is not set. Searching...") + else() + get_filename_component(CURRENT_SEARCH_DIR "$ENV{WOLFSSL_ROOT}" ABSOLUTE) + IS_WOLFSSL_SOURCE("${CURRENT_SEARCH_DIR}" FOUND_WOLFSSL) + if( FOUND_WOLFSSL ) + message(STATUS "Found WOLFSSL_ROOT via Environment Variable:") + else() + message(FATAL_ERROR "WOLFSSL_ROOT Environment Variable defined, but path not found:") + message(STATUS "$ENV{WOLFSSL_ROOT}") + endif() + endif() + else() + get_filename_component(CURRENT_SEARCH_DIR "${${OUTPUT_FOUND_WOLFSSL_DIRECTORY}}" ABSOLUTE) + IS_WOLFSSL_SOURCE("${CURRENT_SEARCH_DIR}" FOUND_WOLFSSL) + if( FOUND_WOLFSSL ) + message(STATUS "Found WOLFSSL_ROOT via prior specification.") + else() + message(FATAL_ERROR "WOLFSSL_ROOT Variable defined, but path not found: ${${OUTPUT_FOUND_WOLFSSL_DIRECTORY}}") + endif() + endif() + + + # we'll start in the CMAKE_CURRENT_SOURCE_DIR, typically [something]/projectname/components/wolfssl + message(STATUS "CMAKE_CURRENT_SOURCE_DIR = ${CMAKE_CURRENT_SOURCE_DIR}") + get_filename_component(CURRENT_SEARCH_DIR "${CMAKE_CURRENT_SOURCE_DIR}" ABSOLUTE) + message(STATUS "CURRENT_SEARCH_DIR = ${CURRENT_SEARCH_DIR}") + string(LENGTH ${CURRENT_SEARCH_DIR} CURRENT_SEARCH_DIR_LENGTH) + + # loop through all the parents, looking for wolfssl + while(NOT CURRENT_SEARCH_DIR STREQUAL "/" AND NOT CURRENT_SEARCH_DIR STREQUAL "" ) + string(LENGTH ${CURRENT_SEARCH_DIR} CURRENT_SEARCH_DIR_LENGTH) + # wolfSSL may simply be in a parent directory, such as for local examples in wolfssl repo + IS_WOLFSSL_SOURCE("${CURRENT_SEARCH_DIR}" FOUND_WOLFSSL) + if( FOUND_WOLFSSL ) + message(STATUS "Found wolfssl in CURRENT_SEARCH_DIR = ${CURRENT_SEARCH_DIR}") + set(${OUTPUT_FOUND_WOLFSSL_DIRECTORY} ${CURRENT_SEARCH_DIR} PARENT_SCOPE) + return() + endif() + + if( THIS_USER ) + # Check for "wolfssl-[username]" subdirectory as we recurse up the directory tree + set(CURRENT_SEARCH_DIR_ALT ${CURRENT_SEARCH_DIR}/wolfssl-${THIS_USER}) + message(STATUS "Looking in ${CURRENT_SEARCH_DIR}") + + #if(EXISTS ${CURRENT_SEARCH_DIR_ALT} AND IS_DIRECTORY ${CURRENT_SEARCH_DIR_ALT} AND EXISTS "${CURRENT_SEARCH_DIR_ALT}/wolfcrypt/src") + IS_WOLFSSL_SOURCE("${CURRENT_SEARCH_DIR_ALT}" FOUND_WOLFSSL ) + if ( FOUND_WOLFSSL ) + message(STATUS "Found wolfssl in user-suffix CURRENT_SEARCH_DIR_ALT = ${CURRENT_SEARCH_DIR_ALT}") + set(${OUTPUT_FOUND_WOLFSSL_DIRECTORY} ${CURRENT_SEARCH_DIR_ALT} PARENT_SCOPE) + return() + endif() + endif() + + # Next check for no user suffix "wolfssl" subdirectory as we recurse up the directory tree + set(CURRENT_SEARCH_DIR_ALT ${CURRENT_SEARCH_DIR}/wolfssl) + # if(EXISTS ${CURRENT_SEARCH_DIR} AND IS_DIRECTORY ${CURRENT_SEARCH_DIR} AND EXISTS "${CURRENT_SEARCH_DIR}/wolfcrypt/src") + IS_WOLFSSL_SOURCE("${CURRENT_SEARCH_DIR_ALT}" FOUND_WOLFSSL ) + if ( FOUND_WOLFSSL ) + message(STATUS "Found wolfssl in CURRENT_SEARCH_DIR = ${CURRENT_SEARCH_DIR}") + set(${OUTPUT_FOUND_WOLFSSL_DIRECTORY} ${CURRENT_SEARCH_DIR} PARENT_SCOPE) + return() + endif() + + # Move up one directory level + set(PRIOR_SEARCH_DIR "${CURRENT_SEARCH_DIR}") + get_filename_component(CURRENT_SEARCH_DIR "${CURRENT_SEARCH_DIR}" DIRECTORY) + message(STATUS "Next CURRENT_SEARCH_DIR = ${CURRENT_SEARCH_DIR}") + if( "${PRIOR_SEARCH_DIR}" STREQUAL "${CURRENT_SEARCH_DIR}" ) + # when the search directory is empty, we'll give up + set(CURRENT_SEARCH_DIR "") + endif() + endwhile() + + # If not found, set the output variable to empty before exiting + set(${OUTPUT_FOUND_WOLFSSL_DIRECTORY} "" PARENT_SCOPE) +endfunction() + + +# Example usage: +# +# Simply find the WOLFSSL_DIRECTORY by searching parent directories: +# FIND_WOLFSSL_DIRECTORY(WOLFSSL_ROOT) +# + +if(CMAKE_BUILD_EARLY_EXPANSION) + message(STATUS "wolfssl component CMAKE_BUILD_EARLY_EXPANSION:") + idf_component_register( + REQUIRES "${COMPONENT_REQUIRES}" + PRIV_REQUIRES # esp_hw_support + "${THIS_INCLUDE_TIMER}" + "${THIS_INCLUDE_DRIVER}" # this will typically only be needed for wolfSSL benchmark + ) + +else() + # not CMAKE_BUILD_EARLY_EXPANSION + message(STATUS "************************************************************************************************") + message(STATUS "wolfssl component config:") + message(STATUS "************************************************************************************************") + + if ( "${CONFIG_TARGET_PLATFORM}" STREQUAL "esp8266") + # There's no esp_timer, no driver components for the ESP8266 + set(THIS_INCLUDE_TIMER "") + set(THIS_INCLUDE_DRIVER "") + else() + set(THIS_INCLUDE_TIMER "esp_timer") + set(THIS_INCLUDE_DRIVER "driver") + endif() + + # search for wolfSSL + # TODO allow for cmake prior def + + if(WOLFSSL_ROOT) + IS_WOLFSSL_SOURCE("${WOLFSSL_ROOT}" FOUND_WOLFSSL) + if(FOUND_WOLFSSL) + message(STATUS "Found WOLFSSL_ROOT via CMake specification.") + else() + # WOLFSSL_ROOT Path specified in CMakeLists.txt is not a valid path + message(FATAL_ERROR "WOLFSSL_ROOT CMake Variable defined, but path not found: ${WOLFSSL_ROOT}\n" + "Try correcting WOLFSSL_ROOT in your project CMakeFile.txt or setting environment variable.") + # Abort CMake after fatal error. + endif() + else() + message(STATUS "Searching for wolfSL source code...") + FIND_WOLFSSL_DIRECTORY(WOLFSSL_ROOT) + endif() + + + if(WOLFSSL_ROOT) + message(STATUS "Confirmed wolfssl directory at: ${WOLFSSL_ROOT}") + else() + message(STATUS "Failed: wolfssl directory not found.") + # Abort. We need wolfssl _somewhere_. + message(FATAL_ERROR "Could not find wolfssl in ${WOLFSSL_ROOT}.\n" + "Try setting WOLFSSL_ROOT environment variable or git clone.") + # Abort CMake after fatal error. + endif() + + set(INCLUDE_PATH ${WOLFSSL_ROOT}) + + set(WOLFSSL_EXTRA_PROJECT_DIR "${WOLFSSL_ROOT}/src/") + + # During regression tests, optionally copy source locally and use: set(USE_LOCAL_TEST_BENCH 1) + set(USE_LOCAL_TEST_BENCH 0) + if(NOT USE_LOCAL_TEST_BENCH) + if( "${CMAKE_PROJECT_NAME}" STREQUAL "hello-world" ) + message(STATUS "Include ${WOLFSSL_ROOT}/wolfcrypt/benchmark") + set(WOLFSSL_EXTRA_PROJECT_DIR "${WOLFSSL_ROOT}/wolfcrypt/benchmark") + endif() + + if( "${CMAKE_PROJECT_NAME}" STREQUAL "wolfssl_benchmark" ) + message(STATUS "Include ${WOLFSSL_ROOT}/wolfcrypt/benchmark") + set(WOLFSSL_EXTRA_PROJECT_DIR "${WOLFSSL_ROOT}/wolfcrypt/benchmark") + endif() + + if( "${CMAKE_PROJECT_NAME}" STREQUAL "wolfssl_test" ) + message(STATUS "Include ${WOLFSSL_ROOT}/wolfcrypt/test") + set(WOLFSSL_EXTRA_PROJECT_DIR "${WOLFSSL_ROOT}/wolfcrypt/test") + endif() + endif() + + set(COMPONENT_SRCDIRS "\"${WOLFSSL_ROOT}/src/\"" + "\"${WOLFSSL_ROOT}/wolfcrypt/src\"" + "\"${WOLFSSL_ROOT}/wolfcrypt/src/port/Espressif\"" + "\"${WOLFSSL_ROOT}/wolfcrypt/src/port/atmel\"" + "\"${WOLFSSL_EXTRA_PROJECT_DIR}\"" + ) # COMPONENT_SRCDIRS + + message(STATUS "This COMPONENT_SRCDIRS = ${COMPONENT_SRCDIRS}") + + # wolfSSL user_settings.h is in the local project. + set(WOLFSSL_PROJECT_DIR "${CMAKE_HOME_DIRECTORY}/components/wolfssl") + + string(REPLACE "/" "//" STR_WOLFSSL_PROJECT_DIR "${WOLFSSL_PROJECT_DIR}") + add_definitions(-DWOLFSSL_USER_SETTINGS_DIR="${STR_WOLFSSL_PROJECT_DIR}//include//user_settings.h") + + # Espressif may take several passes through this makefile. Check to see if we found IDF + string(COMPARE EQUAL "${PROJECT_SOURCE_DIR}" "" WOLFSSL_FOUND_IDF) + + # get a list of all wolfcrypt assembly files; we'll exclude them as they don't target Xtensa + file(GLOB EXCLUDE_ASM *.S) + file(GLOB EXCLUDE_ASM ${CMAKE_SOURCE_DIR} "${WOLFSSL_ROOT}/wolfcrypt/src/*.S") + + message(STATUS "IDF_PATH = $ENV{IDF_PATH}") + message(STATUS "PROJECT_SOURCE_DIR = ${PROJECT_SOURCE_DIR}") + message(STATUS "EXCLUDE_ASM = ${EXCLUDE_ASM}") + + # + # Check to see if there's both a local copy and EDP-IDF copy of the wolfssl and/or wolfssh components. + # + if( EXISTS "${WOLFSSL_PROJECT_DIR}" AND EXISTS "$ENV{IDF_PATH}/components/wolfssl/" ) + # + # wolfSSL found in both ESP-IDF and local project - needs to be resolved by user + # + message(STATUS "") + message(STATUS "**************************************************************************************") + message(STATUS "") + message(STATUS "Error: Found components/wolfssl in both local project and IDF_PATH") + message(STATUS "") + message(STATUS "To proceed: ") + message(STATUS "") + message(STATUS "Remove either the local project component: ${WOLFSSL_PROJECT_DIR} ") + message(STATUS "or the Espressif shared component installed at: $ENV{IDF_PATH}/components/wolfssl/ ") + message(STATUS "") + message(STATUS "") + message(STATUS "**************************************************************************************") + message(STATUS "") + + message(FATAL_ERROR "Please use wolfSSL in either local project or Espressif components, but not both.") + # Abort CMake after fatal error. + + # Optional: if you change the above FATAL_ERROR to STATUS you can warn at runtime with this macro definition: + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DWOLFSSL_MULTI_INSTALL_WARNING") + + else() + if( EXISTS "$ENV{IDF_PATH}/components/wolfssl/" ) + # + # wolfSSL found in ESP-IDF components and is assumed to be already configured in user_settings.h via setup. + # + message(STATUS "") + message(STATUS "Using components/wolfssl in IDF_PATH = $ENV{IDF_PATH}") + message(STATUS "") + else() + # + # wolfSSL is not an ESP-IDF component. + # We need to now determine if it is local and if so if it is part of the wolfSSL repo, + # or if wolfSSL is simply installed as a local component. + # + + if( EXISTS "${WOLFSSL_PROJECT_DIR}" ) + # + # wolfSSL found in local project. + # + if( EXISTS "${WOLFSSL_PROJECT_DIR}/wolfcrypt/" ) + message(STATUS "") + message(STATUS "Using installed project ./components/wolfssl in CMAKE_HOME_DIRECTORY = ${CMAKE_HOME_DIRECTORY}") + message(STATUS "") + # + # Note we already checked above and confirmed there's not another wolfSSL installed in the ESP-IDF components. + # + # We won't do anything else here, as it will be assumed the original install completed successfully. + # + else() # full wolfSSL not installed in local project + # + # This is the developer repo mode. wolfSSL will be assumed to be not installed to ESP-IDF nor local project + # In this configuration, we are likely running a wolfSSL example found directly in the repo. + # + message(STATUS "") + message(STATUS "Using developer repo ./components/wolfssl in CMAKE_HOME_DIRECTORY = ${CMAKE_HOME_DIRECTORY}") + message(STATUS "") + + message(STATUS "************************************************************************************************") + # When in developer mode, we are typically running wolfSSL examples such as benchmark or test directories. + # However, the as-cloned or distributed wolfSSL does not have the ./include/ directory, so we'll add it as needed. + # + # first check if there's a [root]/include/user_settings.h + if( EXISTS "${WOLFSSL_ROOT}/include/user_settings.h" ) + message(FATAL_ERROR "Found stray wolfSSL user_settings.h in " + "${WOLFSSL_ROOT}/include/user_settings.h " + " (please move it to ${WOLFSSL_PROJECT_DIR}/include/user_settings.h )") + # Abort CMake after fatal error. + else() + # we won't overwrite an existing user settings file, just note that we already have one: + if( EXISTS "${WOLFSSL_PROJECT_DIR}/include/user_settings.h" ) + message(STATUS "Using existing wolfSSL user_settings.h in " + "${WOLFSSL_PROJECT_DIR}/include/user_settings.h") + else() + message(STATUS "Installing wolfSSL user_settings.h to " + "${WOLFSSL_PROJECT_DIR}/include/user_settings.h") + file(COPY "${WOLFSSL_ROOT}/IDE/Espressif/ESP-IDF/user_settings.h" + DESTINATION "${CMAKE_HOME_DIRECTORY}/wolfssl/include/") + endif() + endif() # user_settings.h + + # next check if there's a [root]/include/config.h + if( EXISTS "${WOLFSSL_ROOT}/include/config.h" ) + message(STATUS "******************************************************************************") + message(STATUS "******************************************************************************") + message(STATUS "Found stray wolfSSL config.h in ${WOLFSSL_ROOT}/include/config.h" ) + message(STATUS " Please move it to ${WOLFSSL_PROJECT_DIR}/include/config.h" ) + message(STATUS "******************************************************************************") + message(STATUS "******************************************************************************") + else() + # we won't overwrite an existing user settings file, just note that we already have one: + if( EXISTS "${WOLFSSL_PROJECT_DIR}/include/config.h" ) + message(STATUS "Using existing wolfSSL config.h ${WOLFSSL_PROJECT_DIR}/include/config.h") + else() + message(STATUS "Installing wolfSSL config.h to ${WOLFSSL_PROJECT_DIR}/include/config.h") + file(COPY "${WOLFSSL_ROOT}/IDE/Espressif/ESP-IDF/dummy_config_h" DESTINATION "${WOLFSSL_PROJECT_DIR}/include/") + file(RENAME "${WOLFSSL_PROJECT_DIR}/include/dummy_config_h" "${WOLFSSL_PROJECT_DIR}/include/config.h") + endif() # Project config.h + endif() # WOLFSSL_ROOT config.h + message(STATUS "************************************************************************************************") + message(STATUS "") + endif() + + else() + # we did not find a ./components/wolfssl/include/ directory from this pass of cmake. + if($WOLFSSL_FOUND_IDF) + message(STATUS "") + message(STATUS "WARNING: wolfSSL not found.") + message(STATUS "") + else() + # probably needs to be re-parsed by Espressif + message(STATUS "wolfSSL found IDF. Project Source:${PROJECT_SOURCE_DIR}") + endif() # else we have not found ESP-IDF yet + endif() # else not a local wolfSSL component + + endif() #else not an ESP-IDF component + endif() # else not local copy and EDP-IDF wolfSSL + + + # 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/FreeRTOS-Kernel/include/freertos") + + string(REPLACE "\\" "/" WOLFSSL_ROOT ${WOLFSSL_ROOT}) + + if(IS_DIRECTORY "${RTOS_IDF_PATH}") + message(STATUS "Found current RTOS path: ${RTOS_IDF_PATH}") + else() + # ESP-IDF prior version 4.4x has a different RTOS directory structure + string(REPLACE "\\" "/" RTOS_IDF_PATH "$ENV{IDF_PATH}/components/freertos/include/freertos") + if(IS_DIRECTORY "${RTOS_IDF_PATH}") + message(STATUS "Found legacy RTOS path: ${RTOS_IDF_PATH}") + else() + message(STATUS "Could not find RTOS path") + endif() + endif() + + # wolfSSL-specific include directories + set(COMPONENT_ADD_INCLUDEDIRS + "./include" # this is the location of local project wolfssl user_settings.h + "\"${WOLFSSL_ROOT}/\"" + "\"${WOLFSSL_ROOT}/wolfssl/\"" + "\"${WOLFSSL_ROOT}/wolfssl/wolfcrypt/\"" + "\"${WOLFSSL_ROOT}/wolfssl/wolfcrypt/port/Espressif\"" + "\"${RTOS_IDF_PATH}/\"" + ) + + # Optionally include cryptoauthlib if present + if(IS_DIRECTORY ${IDF_PATH}/components/cryptoauthlib) + list(APPEND COMPONENT_ADD_INCLUDEDIRS "../cryptoauthlib/lib") + endif() + + list(APPEND COMPONENT_ADD_INCLUDEDIRS "\"${WOLFSSL_ROOT}/wolfssl/\"") + list(APPEND COMPONENT_ADD_INCLUDEDIRS "\"${WOLFSSL_ROOT}/wolfssl/wolfcrypt/\"") + + + # Some files are known to be included elsewhere, or not used for Espressif + set(COMPONENT_SRCEXCLUDE + "\"${WOLFSSL_ROOT}/src/bio.c\"" + "\"${WOLFSSL_ROOT}/src/conf.c\"" + "\"${WOLFSSL_ROOT}/src/misc.c\"" + "\"${WOLFSSL_ROOT}/src/pk.c\"" + "\"${WOLFSSL_ROOT}/src/ssl_asn1.c\"" # included by ssl.c + "\"${WOLFSSL_ROOT}/src/ssl_bn.c\"" # included by ssl.c + "\"${WOLFSSL_ROOT}/src/ssl_certman.c\"" # included by ssl.c + "\"${WOLFSSL_ROOT}/src/ssl_crypto.c\"" # included by ssl.c + "\"${WOLFSSL_ROOT}/src/ssl_misc.c\"" # included by ssl.c + "\"${WOLFSSL_ROOT}/src/x509.c\"" + "\"${WOLFSSL_ROOT}/src/x509_str.c\"" + "\"${WOLFSSL_ROOT}/wolfcrypt/src/evp.c\"" + "\"${WOLFSSL_ROOT}/wolfcrypt/src/misc.c\"" + "\"${WOLFSSL_ROOT}/wolfcrypt/src/sp_sm2_arm32.c\"" + "\"${WOLFSSL_ROOT}/wolfcrypt/src/sp_sm2_arm64.c\"" + "\"${WOLFSSL_ROOT}/wolfcrypt/src/sp_sm2_armthumb.c\"" + "\"${WOLFSSL_ROOT}/wolfcrypt/src/sp_sm2_c32.c\"" + "\"${WOLFSSL_ROOT}/wolfcrypt/src/sp_sm2_c64.c\"" + "\"${WOLFSSL_ROOT}/wolfcrypt/src/sp_sm2_cortexm.c\"" + "\"${WOLFSSL_ROOT}/wolfcrypt/src/sp_sm2_x86_64.c\"" + "\"${WOLFSSL_ROOT}/wolfcrypt/src/sp_sm2_x86_64_asm.S\"" + "\"${EXCLUDE_ASM}\"" + ) + + spaces2list(COMPONENT_REQUIRES) + + separate_arguments(COMPONENT_SRCDIRS NATIVE_COMMAND "${COMPONENT_SRCDIRS}") + separate_arguments(COMPONENT_SRCEXCLUDE NATIVE_COMMAND "${COMPONENT_SRCEXCLUDE}") + separate_arguments(COMPONENT_ADD_INCLUDEDIRS NATIVE_COMMAND "${COMPONENT_ADD_INCLUDEDIRS}") + + # + # See https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/build-system.html#example-component-requirements + # + message(STATUS "COMPONENT_SRCDIRS = ${COMPONENT_SRCDIRS}") + message(STATUS "COMPONENT_ADD_INCLUDEDIRS = ${COMPONENT_ADD_INCLUDEDIRS}") + message(STATUS "COMPONENT_REQUIRES = ${COMPONENT_REQUIRES}") + message(STATUS "COMPONENT_SRCEXCLUDE = ${COMPONENT_SRCEXCLUDE}") + + # + # see https://docs.espressif.com/projects/esp-idf/en/stable/esp32/migration-guides/release-5.x/build-system.html?highlight=space%20path + # + set(EXTRA_COMPONENT_DIRS "${COMPONENT_SRCDIRS}") + idf_component_register( + SRC_DIRS "${COMPONENT_SRCDIRS}" + INCLUDE_DIRS "${COMPONENT_ADD_INCLUDEDIRS}" + REQUIRES "${COMPONENT_REQUIRES}" + EXCLUDE_SRCS "${COMPONENT_SRCEXCLUDE}" + PRIV_REQUIRES + "${THIS_INCLUDE_TIMER}" + "${THIS_INCLUDE_DRIVER}" # this will typically only be needed for wolfSSL benchmark + ) + + # Some optional diagnostics. Verbose ones are truncated. + if (VERBOSE_COMPONENT_MESSAGES) + get_cmake_property(_variableNames VARIABLES) + list (SORT _variableNames) + message(STATUS "") + message(STATUS "ALL VARIABLES BEGIN") + message(STATUS "") + foreach (_variableName ${_variableNames}) + if ( ("${_variableName}" STREQUAL "bootloader_binary_files") + OR ("${_variableName}" STREQUAL "Component paths") + OR ("${_variableName}" STREQUAL "component_targets") + OR ("${_variableName}" STREQUAL "__COMPONENT_TARGETS") + OR ("${_variableName}" STREQUAL "CONFIGS_LIST") + OR ("${_variableName}" STREQUAL "__CONFIG_VARIABLES") + OR ("${_variableName}" STREQUAL "val") + OR ("${_variableName}" MATCHES "^__idf_") + ) + # Truncate the displayed value: + string(SUBSTRING "${${_variableName}}" 0 70 truncatedValue) + message(STATUS "${_variableName} = ${truncatedValue} ... (truncated)") + else() + message(STATUS "${_variableName}=${${_variableName}}") + endif() + endforeach() + message(STATUS "") + message(STATUS "ALL VARIABLES END") + message(STATUS "") + endif() + + # target_sources(wolfssl PRIVATE "\"${WOLFSSL_ROOT}/wolfssl/\"" "\"${WOLFSSL_ROOT}/wolfssl/wolfcrypt\"") + +endif() # CMAKE_BUILD_EARLY_EXPANSION + + + +# check to see if there's both a local copy and EDP-IDF copy of the wolfssl components +if( EXISTS "${WOLFSSL_PROJECT_DIR}" AND EXISTS "$ENV{IDF_PATH}/components/wolfssl/" ) + message(STATUS "") + message(STATUS "") + message(STATUS "********************************************************************") + message(STATUS "WARNING: Found components/wolfssl in both local project and IDF_PATH") + message(STATUS "********************************************************************") + message(STATUS "") +endif() +# end multiple component check + + +# +# LIBWOLFSSL_SAVE_INFO(VAR_OUPUT THIS_VAR VAR_RESULT) +# +# Save the THIS_VAR as a string in a macro called VAR_OUPUT +# +# VAR_OUPUT: the name of the macro to define +# THIS_VAR: the OUTPUT_VARIABLE result from a execute_process() +# VAR_RESULT: the RESULT_VARIABLE from a execute_process(); "0" if successful. +# +function ( LIBWOLFSSL_SAVE_INFO VAR_OUPUT THIS_VAR VAR_RESULT ) + # is the RESULT_VARIABLE output value 0? If so, IS_VALID_VALUE is true. + string(COMPARE EQUAL "${VAR_RESULT}" "0" IS_VALID_VALUE) + + # if we had a successful operation, save the THIS_VAR in VAR_OUPUT + if(${IS_VALID_VALUE}) + # strip newline chars in THIS_VAR parameter and save in VAR_VALUE + string(REPLACE "\n" "" VAR_VALUE ${THIS_VAR}) + + # we'll could percolate the value to the parent for possible later use + # set(${VAR_OUPUT} ${VAR_VALUE} PARENT_SCOPE) + + # but we're only using it here in this function + set(${VAR_OUPUT} ${VAR_VALUE}) + + # we'll print what we found to the console + message(STATUS "Found ${VAR_OUPUT}=${VAR_VALUE}") + + # the interesting part is defining the VAR_OUPUT name a value to use in the app + add_definitions(-D${VAR_OUPUT}=\"${VAR_VALUE}\") + else() + # if we get here, check the execute_process command and parameters. + message(STATUS "LIBWOLFSSL_SAVE_INFO encountered a non-zero VAR_RESULT") + set(${VAR_OUPUT} "Unknown") + endif() +endfunction() # LIBWOLFSSL_SAVE_INFO + +# create some programmatic #define values that will be used by ShowExtendedSystemInfo(). +# see wolfcrypt\src\port\Espressif\esp32_utl.c +if(NOT CMAKE_BUILD_EARLY_EXPANSION) + set (git_cmd "git") + message(STATUS "Adding macro definitions:") + + # LIBWOLFSSL_VERSION_GIT_ORIGIN: git config --get remote.origin.url + execute_process(WORKING_DIRECTORY ${WOLFSSL_ROOT} COMMAND ${git_cmd} "config" "--get" "remote.origin.url" OUTPUT_VARIABLE TMP_OUT RESULT_VARIABLE TMP_RES ERROR_QUIET ) + LIBWOLFSSL_SAVE_INFO(LIBWOLFSSL_VERSION_GIT_ORIGIN "${TMP_OUT}" "${TMP_RES}") + + # LIBWOLFSSL_VERSION_GIT_BRANCH: git rev-parse --abbrev-ref HEAD + execute_process(WORKING_DIRECTORY ${WOLFSSL_ROOT} COMMAND ${git_cmd} "rev-parse" "--abbrev-ref" "HEAD" OUTPUT_VARIABLE TMP_OUT RESULT_VARIABLE TMP_RES ERROR_QUIET ) + LIBWOLFSSL_SAVE_INFO(LIBWOLFSSL_VERSION_GIT_BRANCH "${TMP_OUT}" "${TMP_RES}") + + # LIBWOLFSSL_VERSION_GIT_HASH: git rev-parse HEAD + execute_process(WORKING_DIRECTORY ${WOLFSSL_ROOT} COMMAND ${git_cmd} "rev-parse" "HEAD" OUTPUT_VARIABLE TMP_OUT RESULT_VARIABLE TMP_RES ERROR_QUIET ) + LIBWOLFSSL_SAVE_INFO(LIBWOLFSSL_VERSION_GIT_HASH "${TMP_OUT}" "${TMP_RES}") + + # LIBWOLFSSL_VERSION_GIT_SHORT_HASH: git rev-parse --short HEAD + execute_process(WORKING_DIRECTORY ${WOLFSSL_ROOT} COMMAND ${git_cmd} "rev-parse" "--short" "HEAD" OUTPUT_VARIABLE TMP_OUT RESULT_VARIABLE TMP_RES ERROR_QUIET ) + LIBWOLFSSL_SAVE_INFO(LIBWOLFSSL_VERSION_GIT_SHORT_HASH "${TMP_OUT}" "${TMP_RES}") + + # LIBWOLFSSL_VERSION_GIT_HASH_DATE git show --no-patch --no-notes --pretty=\'\%cd\' + execute_process(WORKING_DIRECTORY ${WOLFSSL_ROOT} COMMAND ${git_cmd} "show" "--no-patch" "--no-notes" "--pretty=\'\%cd\'" OUTPUT_VARIABLE TMP_OUT RESULT_VARIABLE TMP_RES ) + LIBWOLFSSL_SAVE_INFO(LIBWOLFSSL_VERSION_GIT_HASH_DATE "${TMP_OUT}" "${TMP_RES}") + + LIBWOLFSSL_SAVE_INFO(LIBWOLFSSL_VERSION_WOLFSSL_ROOT "${WOLFSSL_ROOT}" "${TMP_RES}") + + message(STATUS "************************************************************************************************") + message(STATUS "wolfssl component config complete!") + message(STATUS "************************************************************************************************") +endif() diff --git a/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/components/wolfssl/README.md b/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/components/wolfssl/README.md new file mode 100644 index 000000000..040c8c0ba --- /dev/null +++ b/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/components/wolfssl/README.md @@ -0,0 +1,9 @@ +# Component wolfSSL + +This `wolfssl` directory exists only for the stand-alone examples. + +The only files of interest are the [CMakeLists.txt](./CMakeLists.txt) that should point +to the wolfSSL source code and the respective [include/user_settings.h](./include/user_settings.h). + +This directory is _not_ included in the publish to the Espressif Registry, as that +mechanism copies the published source code to the local component directory as needed. diff --git a/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/components/wolfssl/include/user_settings.h b/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/components/wolfssl/include/user_settings.h new file mode 100644 index 000000000..41f588a01 --- /dev/null +++ b/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/components/wolfssl/include/user_settings.h @@ -0,0 +1,508 @@ +/* user_settings.h + * + * Copyright (C) 2006-2023 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL 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 2 of the License, or + * (at your option) any later version. + * + * wolfSSL 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +#include /* essential to chip set detection */ + +#undef WOLFSSL_ESPIDF +#undef WOLFSSL_ESP32 +#undef WOLFSSL_ESPWROOM32SE +#undef WOLFSSL_ESP32 +#undef WOLFSSL_ESP8266 + +#define WOLFSSL_ESPIDF + +/* The Espressif sdkconfig will have chipset info. +** +** Possible values: +** +** CONFIG_IDF_TARGET_ESP32 +** CONFIG_IDF_TARGET_ESP32S2 +** CONFIG_IDF_TARGET_ESP32S3 +** CONFIG_IDF_TARGET_ESP32C3 +** CONFIG_IDF_TARGET_ESP32C6 +*/ + +/* Optionally enable some wolfSSH settings */ +#ifdef ESP_ENABLE_WOLFSSH + /* The default SSH Windows size is massive for an embedded target. Limit it: */ + #define DEFAULT_WINDOW_SZ 2000 + + /* These may be defined in cmake for other examples: */ + #undef WOLFSSH_TERM + #define WOLFSSH_TERM + + #undef DEBUG_WOLFSSH + #define DEBUG_WOLFSSH + + #undef WOLFSSL_KEY_GEN + #define WOLFSSL_KEY_GEN + + #undef WOLFSSL_PTHREADS + #define WOLFSSL_PTHREADS + + #define WOLFSSH_TEST_SERVER + #define WOLFSSH_TEST_THREADING + +#endif /* ESP_ENABLE_WOLFSSH */ + +/* when you want to use SINGLE THREAD */ +/* #define SINGLE_THREADED */ + +/* + * choose ONE of these Espressif chips to define: + * + * WOLFSSL_ESP32 + * WOLFSSL_ESPWROOM32SE + * WOLFSSL_ESP8266 + */ + +#define WOLFSSL_ESP32 + +/* optionally turn off SHA512/224 SHA512/256 */ +/* #define WOLFSSL_NOSHA512_224 */ +/* #define WOLFSSL_NOSHA512_256 */ + +/* when you want to use SINGLE THREAD. Note Default ESP-IDF is FreeRTOS */ +/* #define SINGLE_THREADED */ + +/* When you don't want to use the old SHA */ +/* #define NO_SHA */ +/* #define NO_OLD_TLS */ + +#define BENCH_EMBEDDED +#define USE_CERT_BUFFERS_2048 + +#define NO_OLD_TLS +/* TLS 1.3 + #define WOLFSSL_TLS13 + #define HAVE_TLS_EXTENSIONS + #define WC_RSA_PSS + #define HAVE_SUPPORTED_CURVES +*/ + +#define HAVE_HKDF +#define HAVE_AEAD + +#define NO_FILESYSTEM + +#define HAVE_AESGCM + +#define WOLFSSL_RIPEMD +/* when you want to use SHA224 */ +/* #define WOLFSSL_SHA224 */ + + +/* when you want to use SHA384 */ +/* #define WOLFSSL_SHA384 */ + +/* #define WOLFSSL_SHA3 */ + +#define WOLFSSL_SHA512 + +#define MY_USE_ECC 1 +#define MY_USE_RSA 0 + +/* We can use either or both ECC and RSA, but must use at least one. */ +#if MY_USE_ECC || MY_USE_RSA + #if MY_USE_ECC + /* ---- ECDSA / ECC ---- */ + #define HAVE_ECC + #define HAVE_CURVE25519 + #define HAVE_ED25519 + + /* + #define HAVE_ECC384 + #define CURVE25519_SMALL + */ + #else + #define WOLFSSH_NO_ECC + /* WOLFSSH_NO_ECDSA is typically defined automatically, + * here for clarity: */ + #define WOLFSSH_NO_ECDSA + #endif + + #if MY_USE_RSA + /* ---- RSA ----- */ + /* #define RSA_LOW_MEM */ + + /* DH disabled by default, needed if ECDSA/ECC also turned off */ + #define HAVE_DH + #else + #define WOLFSSH_NO_RSA + #endif +#else + #error "Either RSA or ECC must be enabled" +#endif + + +/* when you want to use pkcs7 */ +/* #define HAVE_PKCS7 */ + +#if defined(HAVE_PKCS7) + #define HAVE_AES_KEYWRAP + #define HAVE_X963_KDF + #define WOLFSSL_AES_DIRECT +#endif + +/* when you want to use aes counter mode */ +/* #define WOLFSSL_AES_DIRECT */ +/* #define WOLFSSL_AES_COUNTER */ + +/* debug options */ +/* #define DEBUG_WOLFSSL */ +/* #define WOLFSSL_ESP32_CRYPT_DEBUG */ +/* #define WOLFSSL_ATECC508A_DEBUG */ + +/* date/time */ +/* if it cannot adjust time in the device, */ +/* enable macro below */ +/* #define NO_ASN_TIME */ +/* #define XTIME time */ + +/* adjust wait-timeout count if you see timeout in RSA HW acceleration */ +#define ESP_RSA_TIMEOUT_CNT 0x249F00 + + +/* USE_FAST_MATH is default */ +#define USE_FAST_MATH + +/***** Use SP_MATH *****/ +/* #undef USE_FAST_MATH */ +/* #define SP_MATH */ +/* #define WOLFSSL_SP_MATH_ALL */ +/* #define WOLFSSL_SP_RISCV32 */ + +/***** Use Integer Heap Math *****/ +/* #undef USE_FAST_MATH */ +/* #define USE_INTEGER_HEAP_MATH */ + + +#define WOLFSSL_SMALL_STACK + +/* The ESP32 has some detailed statup information available:*/ +#define HAVE_VERSION_EXTENDED_INFO + +/* optional SM4 Ciphers. See https://github.com/wolfSSL/wolfsm */ +/* +#define WOLFSSL_SM2 +#define WOLFSSL_SM3 +#define WOLFSSL_SM4 +*/ + +#if defined(WOLFSSL_SM2) || defined(WOLFSSL_SM3) || defined(WOLFSSL_SM4) + /* SM settings, possible cipher suites: + + TLS13-AES128-GCM-SHA256 + TLS13-CHACHA20-POLY1305-SHA256 + TLS13-SM4-GCM-SM3 + TLS13-SM4-CCM-SM3 + + #define WOLFSSL_ESP32_CIPHER_SUITE "TLS13-SM4-GCM-SM3" + #define WOLFSSL_ESP32_CIPHER_SUITE "TLS13-SM4-CCM-SM3" + #define WOLFSSL_ESP32_CIPHER_SUITE "ECDHE-ECDSA-SM4-CBC-SM3" + #define WOLFSSL_ESP32_CIPHER_SUITE "ECDHE-ECDSA-SM4-GCM-SM3" + #define WOLFSSL_ESP32_CIPHER_SUITE "ECDHE-ECDSA-SM4-CCM-SM3" + #define WOLFSSL_ESP32_CIPHER_SUITE "TLS13-SM4-GCM-SM3:" \ + "TLS13-SM4-CCM-SM3:" + */ + + #undef WOLFSSL_BASE16 + #define WOLFSSL_BASE16 /* required for WOLFSSL_SM2 */ + + #undef WOLFSSL_SM4_ECB + #define WOLFSSL_SM4_ECB + + #undef WOLFSSL_SM4_CBC + #define WOLFSSL_SM4_CBC + + #undef WOLFSSL_SM4_CTR + #define WOLFSSL_SM4_CTR + + #undef WOLFSSL_SM4_GCM + #define WOLFSSL_SM4_GCM + + #undef WOLFSSL_SM4_CCM + #define WOLFSSL_SM4_CCM + + #define HAVE_POLY1305 + #define HAVE_CHACHA + + #undef HAVE_AESGCM + #define HAVE_AESGCM +#else + /* default settings */ + #define USE_CERT_BUFFERS_2048 +#endif + +/* esp32-wroom-32se specific definition */ +#if defined(WOLFSSL_ESPWROOM32SE) + #define WOLFSSL_ATECC508A + #define HAVE_PK_CALLBACKS + /* when you want to use a custom slot allocation for ATECC608A */ + /* unless your configuration is unusual, you can use default */ + /* implementation. */ + /* #define CUSTOM_SLOT_ALLOCATION */ +#endif + +/* Default is HW enabled unless turned off. +** Uncomment these lines to force SW instead of HW acceleration */ + +#if defined(CONFIG_IDF_TARGET_ESP32) || defined(WOLFSSL_ESPWROOM32SE) + /* wolfSSL HW Acceleration supported on ESP32. Uncomment to disable: */ + /* #define NO_ESP32_CRYPT */ + /* #define NO_WOLFSSL_ESP32_CRYPT_HASH */ + /* #define NO_WOLFSSL_ESP32_CRYPT_AES */ + /* #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI */ + /* #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_MP_MUL */ + /* #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_MULMOD */ + /* #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_EXPTMOD */ + + /* These are defined automatically in esp32-crypt.h, here for clarity: */ + /* no SHA224 HW on ESP32 */ + #define NO_WOLFSSL_ESP32_CRYPT_HASH_SHA224 + + /* 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 */ + #define EPS_RSA_EXPT_XBTIS 32 + + /* X and Y of X * Y mod P greater than */ + #undef ESP_RSA_MULM_BITS + #define ESP_RSA_MULM_BITS 16 + + /***** END CONFIG_IDF_TARGET_ESP32 *****/ + +#elif defined(CONFIG_IDF_TARGET_ESP32S2) + /* wolfSSL HW Acceleration supported on ESP32-S2. Uncomment to disable: */ + /* #define NO_ESP32_CRYPT */ + /* #define NO_WOLFSSL_ESP32_CRYPT_HASH */ + /* Note: There's no AES192 HW on the ESP32-S2; falls back to SW */ + /* #define NO_WOLFSSL_ESP32_CRYPT_AES */ + /* #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI */ + /* #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_MP_MUL */ + /* #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_MULMOD */ + /* #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_EXPTMOD */ + /***** END CONFIG_IDF_TARGET_ESP32S2 *****/ + +#elif defined(CONFIG_IDF_TARGET_ESP32S3) + /* wolfSSL HW Acceleration supported on ESP32-S3. Uncomment to disable: */ + /* #define NO_ESP32_CRYPT */ + /* #define NO_WOLFSSL_ESP32_CRYPT_HASH */ + /* Note: There's no AES192 HW on the ESP32-S3; falls back to SW */ + /* #define NO_WOLFSSL_ESP32_CRYPT_AES */ + /* #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI */ + /* #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_MP_MUL */ + /* #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_MULMOD */ + /* #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_EXPTMOD */ + /***** END CONFIG_IDF_TARGET_ESP32S3 *****/ + +#elif defined(CONFIG_IDF_TARGET_ESP32C2) || \ + defined(CONFIG_IDF_TARGET_ESP8684) + /* ESP8684 is essentially ESP32-C2 chip + flash embedded together in a + * single QFN 4x4 mm package. Out of released documentation, Technical + * Reference Manual as well as ESP-IDF Programming Guide is applicable + * to both ESP32-C2 and ESP8684. + * + * See: https://www.esp32.com/viewtopic.php?f=5&t=27926#:~:text=ESP8684%20is%20essentially%20ESP32%2DC2,both%20ESP32%2DC2%20and%20ESP8684. */ + + /* wolfSSL HW Acceleration supported on ESP32-C2. Uncomment to disable: */ + /* #define NO_ESP32_CRYPT */ + /* #define NO_WOLFSSL_ESP32_CRYPT_HASH */ /* to disable all SHA HW */ + + /* These are defined automatically in esp32-crypt.h, here for clarity */ + #define NO_WOLFSSL_ESP32_CRYPT_HASH_SHA384 /* no SHA384 HW on C2 */ + #define NO_WOLFSSL_ESP32_CRYPT_HASH_SHA512 /* no SHA512 HW on C2 */ + + /* There's no AES or RSA/Math accelerator on the ESP32-C2 + * Auto defined with NO_WOLFSSL_ESP32_CRYPT_RSA_PRI, for clarity: */ + #define NO_WOLFSSL_ESP32_CRYPT_AES + #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI + #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_MP_MUL + #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_MULMOD + #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_EXPTMOD + /***** END CONFIG_IDF_TARGET_ESP32C2 *****/ + +#elif defined(CONFIG_IDF_TARGET_ESP32C3) + /* wolfSSL HW Acceleration supported on ESP32-C3. Uncomment to disable: */ + + /* #define NO_ESP32_CRYPT */ + /* #define NO_WOLFSSL_ESP32_CRYPT_HASH */ /* to disable all SHA HW */ + + /* These are defined automatically in esp32-crypt.h, here for clarity: */ + #define NO_WOLFSSL_ESP32_CRYPT_HASH_SHA384 /* no SHA384 HW on C6 */ + #define NO_WOLFSSL_ESP32_CRYPT_HASH_SHA512 /* no SHA512 HW on C6 */ + + /* #define NO_WOLFSSL_ESP32_CRYPT_AES */ + /* #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI */ + /* #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_MP_MUL */ + /* #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_MULMOD */ + /* #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_EXPTMOD */ + /***** END CONFIG_IDF_TARGET_ESP32C3 *****/ + +#elif defined(CONFIG_IDF_TARGET_ESP32C6) + /* wolfSSL HW Acceleration supported on ESP32-C6. Uncomment to disable: */ + + /* #define NO_ESP32_CRYPT */ + /* #define NO_WOLFSSL_ESP32_CRYPT_HASH */ + /* These are defined automatically in esp32-crypt.h, here for clarity: */ + #define NO_WOLFSSL_ESP32_CRYPT_HASH_SHA384 /* no SHA384 HW on C6 */ + #define NO_WOLFSSL_ESP32_CRYPT_HASH_SHA512 /* no SHA512 HW on C6 */ + + /* #define NO_WOLFSSL_ESP32_CRYPT_AES */ + /* #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI */ + /* #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_MP_MUL */ + /* #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_MULMOD */ + /* #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_EXPTMOD */ + /***** END CONFIG_IDF_TARGET_ESP32C6 *****/ + +#elif defined(CONFIG_IDF_TARGET_ESP32H2) + /* wolfSSL Hardware Acceleration not yet implemented */ + #define NO_ESP32_CRYPT + #define NO_WOLFSSL_ESP32_CRYPT_HASH + #define NO_WOLFSSL_ESP32_CRYPT_AES + #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI + /***** END CONFIG_IDF_TARGET_ESP32H2 *****/ + +#elif defined(CONFIG_IDF_TARGET_ESP8266) + /* TODO: Revisit ESP8266 */ + #define NO_ESP32_CRYPT + #define NO_WOLFSSL_ESP32_CRYPT_HASH + #define NO_WOLFSSL_ESP32_CRYPT_AES + #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI + /***** END CONFIG_IDF_TARGET_ESP266 *****/ + +#elif defined(CONFIG_IDF_TARGET_ESP8684) + /* There's no Hardware Acceleration available on ESP8684 */ + #define NO_ESP32_CRYPT + #define NO_WOLFSSL_ESP32_CRYPT_HASH + #define NO_WOLFSSL_ESP32_CRYPT_AES + #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI + /***** END CONFIG_IDF_TARGET_ESP8684 *****/ + +#else + /* Anything else encountered, disable HW accleration */ + #define NO_ESP32_CRYPT + #define NO_WOLFSSL_ESP32_CRYPT_HASH + #define NO_WOLFSSL_ESP32_CRYPT_AES + #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI +#endif /* CONFIG_IDF_TARGET Check */ + +/* Debug options: + +#define ESP_VERIFY_MEMBLOCK +#define DEBUG_WOLFSSL +#define DEBUG_WOLFSSL_VERBOSE +#define DEBUG_WOLFSSL_SHA_MUTEX +#define WOLFSSL_ESP32_CRYPT_DEBUG +#define WOLFSSL_ESP32_CRYPT_HASH_SHA224_DEBUG +#define NO_RECOVER_SOFTWARE_CALC +#define WOLFSSL_TEST_STRAY 1 +#define USE_ESP_DPORT_ACCESS_READ_BUFFER +#define WOLFSSL_ESP32_HW_LOCK_DEBUG +#define WOLFSSL_DEBUG_ESP_RSA_MULM_BITS +#define ESP_DISABLE_HW_TASK_LOCK +*/ + +/* Pause in a loop rather than exit. */ +#define WOLFSSL_ESPIDF_ERROR_PAUSE + +/* #define WOLFSSL_HW_METRICS */ + +/* for test.c */ +/* #define HASH_SIZE_LIMIT */ + +/* Optionally turn off HW math checks */ +/* #define NO_HW_MATH_TEST */ + +/* Optionally include alternate HW test library: alt_hw_test.h */ +/* When enabling, the ./components/wolfssl/CMakeLists.txt file + * will need the name of the library in the idf_component_register + * for the PRIV_REQUIRES list. */ +/* #define INCLUDE_ALT_HW_TEST */ + +/* optionally turn off individual math HW acceleration features */ + +/* Turn off Large Number ESP32 HW Multiplication: +** [Z = X * Y] in esp_mp_mul() */ +/* #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_MP_MUL */ + +/* Turn off Large Number ESP32 HW Modular Exponentiation: +** [Z = X^Y mod M] in esp_mp_exptmod() */ +/* #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_EXPTMOD */ + +/* Turn off Large Number ESP32 HW Modular Multiplication +** [Z = X * Y mod M] in esp_mp_mulmod() */ +/* #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_MULMOD */ + +#define WOLFSSL_PUBLIC_MP /* used by benchmark */ +#define USE_CERT_BUFFERS_2048 + +/* when turning on ECC508 / ECC608 support +#define WOLFSSL_ESPWROOM32SE +#define HAVE_PK_CALLBACKS +#define WOLFSSL_ATECC508A +#define ATCA_WOLFSSL +*/ + +/* optional SM4 Ciphers. See https://github.com/wolfSSL/wolfsm +#define WOLFSSL_SM2 +#define WOLFSSL_SM3 +#define WOLFSSL_SM4 +*/ + +#if defined(WOLFSSL_SM2) || defined(WOLFSSL_SM3) || defined(WOLFSSL_SM4) + #include + #define CTX_CA_CERT root_sm2 + #define CTX_CA_CERT_SIZE sizeof_root_sm2 + #define CTX_CA_CERT_TYPE WOLFSSL_FILETYPE_PEM + #define CTX_SERVER_CERT server_sm2 + #define CTX_SERVER_CERT_SIZE sizeof_server_sm2 + #define CTX_SERVER_CERT_TYPE WOLFSSL_FILETYPE_PEM + #define CTX_SERVER_KEY server_sm2_priv + #define CTX_SERVER_KEY_SIZE sizeof_server_sm2_priv + #define CTX_SERVER_KEY_TYPE WOLFSSL_FILETYPE_PEM + + #undef WOLFSSL_BASE16 + #define WOLFSSL_BASE16 +#else + #define USE_CERT_BUFFERS_2048 + #define USE_CERT_BUFFERS_256 + #define CTX_CA_CERT ca_cert_der_2048 + #define CTX_CA_CERT_SIZE sizeof_ca_cert_der_2048 + #define CTX_CA_CERT_TYPE WOLFSSL_FILETYPE_ASN1 + #define CTX_SERVER_CERT server_cert_der_2048 + #define CTX_SERVER_CERT_SIZE sizeof_server_cert_der_2048 + #define CTX_SERVER_CERT_TYPE WOLFSSL_FILETYPE_ASN1 + #define CTX_SERVER_KEY server_key_der_2048 + #define CTX_SERVER_KEY_SIZE sizeof_server_key_der_2048 + #define CTX_SERVER_KEY_TYPE WOLFSSL_FILETYPE_ASN1 +#endif + +/* See settings.h for some of the possible hardening options: + * + * #define NO_ESPIDF_DEFAULT + * #define WC_NO_CACHE_RESISTANT + * #define WC_AES_BITSLICED + * #define HAVE_AES_ECB + * #define HAVE_AES_DIRECT + */ diff --git a/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/main/CMakeLists.txt b/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/main/CMakeLists.txt new file mode 100644 index 000000000..d58c2ae1c --- /dev/null +++ b/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/main/CMakeLists.txt @@ -0,0 +1,155 @@ +# [wolfSSL Project]/main/CMakeLists.txt +# +# Copyright (C) 2006-2023 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 2 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 this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA +# +# cmake for WOLFSSH Espressif projects +# +# See https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/build-system.html +# wolfSSL wolfSSH Espressif Example Project/main/CMakeLists.txt +# v1.0 +# +message(STATUS "main cmake found WOLFSSL_COMPONENT_NAME = ${WOLFSSL_COMPONENT_NAME}") + +if(WIN32) + # Windows-specific configuration here + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DWOLFSSL_CMAKE_SYSTEM_NAME_WINDOWS") + message("Detected Windows") +endif() +if(CMAKE_HOST_UNIX) + message("Detected UNIX") +endif() +if(APPLE) + message("Detected APPLE") +endif() +if(CMAKE_HOST_UNIX AND (NOT APPLE) AND EXISTS "/proc/sys/fs/binfmt_misc/WSLInterop") + # Windows-specific configuration here + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DWOLFSSL_CMAKE_SYSTEM_NAME_WSL") + message("Detected WSL") +endif() +if(CMAKE_HOST_UNIX AND (NOT APPLE) AND (NOT WIN32)) + # Windows-specific configuration here + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DWOLFSSL_CMAKE_SYSTEM_NAME_LINUX") + message("Detected Linux") +endif() +if(APPLE) + # Windows-specific configuration here + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DWOLFSSL_CMAKE_SYSTEM_NAME_APPLE") + message("Detected Apple") +endif() +set (git_cmd "git") + +if( EXISTS "${CMAKE_HOME_DIRECTORY}/components/wolfssl/" AND EXISTS "$ENV{IDF_PATH}/components/wolfssl/" ) + # + # wolfSSL found in both ESP-IDF and local project - needs to be resolved by user + # + message(STATUS "") + message(STATUS "WARNING: Found components/wolfssl in both local project and IDF_PATH") + message(STATUS "") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DWOLFSSL_MULTI_INSTALL_WARNING") +endif() + +if( "$ENV{IDF_COMPONENT_REGISTRY_URL}" STREQUAL "https://components-staging.espressif.com" ) + if( ("${managed_components}" STREQUAL "") AND ("${component_manager_interface_version}" STREQUAL "") ) + # We've found a staging component, but did not detect the component manager + if(EXISTS ${CMAKE_CURRENT_LIST_DIR}/../components/mywolfssh/CMakeLists.txt) + # This is typically during publish-time build test + message(STATUS "Set name mywolfssh (1)") + set(WOLFSSL_COMPONENT_NAME "mywolfssl") + set(WOLFSSH_COMPONENT_NAME "mywolfssh") + else() + if(EXISTS ${CMAKE_CURRENT_LIST_DIR}/../managed_components/gojimmypi__mywolfmqtt/CMakeLists.txt) + # This is typically upon creating a project from managed component examples + message(STATUS "Set name mywolfssh (2)") + set(WOLFSSL_COMPONENT_NAME "mywolfssl") + set(WOLFSSH_COMPONENT_NAME "mywolfssh") + else() + message(STATUS "Set name wolfmqtt (1) CMAKE_CURRENT_LIST_DIR = ${CMAKE_CURRENT_LIST_DIR}") + set(WOLFSSL_COMPONENT_NAME "wolfssl") + set(WOLFSSH_COMPONENT_NAME "wolfssh") + endif() + endif() + else() + message(STATUS "Set name mywolfssh (3)") + set(WOLFSSL_COMPONENT_NAME "mywolfssl") + set(WOLFSSH_COMPONENT_NAME "mywolfssh") + endif() +else() + message(STATUS "Set name wolfssh (2)") + set(WOLFSSL_COMPONENT_NAME "wolfssl") + set(WOLFSSH_COMPONENT_NAME "wolfssh") +endif() + +## register_component() +idf_component_register( + SRCS main.c echoserver.c time_helper.c wifi_connect.c + INCLUDE_DIRS "." "./include") +# + +# +# LIBWOLFSSL_SAVE_INFO(VAR_OUPUT THIS_VAR VAR_RESULT) +# +# Save the THIS_VAR as a string in a macro called VAR_OUPUT +# +# VAR_OUPUT: the name of the macro to define +# THIS_VAR: the OUTPUT_VARIABLE result from a execute_process() +# VAR_RESULT: the RESULT_VARIABLE from a execute_process(); "0" if successful. +# +function ( LIBWOLFSSL_SAVE_INFO VAR_OUPUT THIS_VAR VAR_RESULT ) + # is the RESULT_VARIABLE output value 0? If so, IS_VALID_VALUE is true. + string(COMPARE EQUAL "${VAR_RESULT}" "0" IS_VALID_VALUE) + + # if we had a successful operation, save the THIS_VAR in VAR_OUPUT + if(${IS_VALID_VALUE}) + # strip newline chars in THIS_VAR parameter and save in VAR_VALUE + string(REPLACE "\n" "" VAR_VALUE ${THIS_VAR}) + + # we'll could percolate the value to the parent for possible later use + # set(${VAR_OUPUT} ${VAR_VALUE} PARENT_SCOPE) + + # but we're only using it here in this function + set(${VAR_OUPUT} ${VAR_VALUE}) + + # we'll print what we found to the console + message(STATUS "Found ${VAR_OUPUT}=${VAR_VALUE}") + + # the interesting part is defining the VAR_OUPUT name a value to use in the app + add_definitions(-D${VAR_OUPUT}=\"${VAR_VALUE}\") + else() + # if we get here, check the execute_process command and parameters. + message(STATUS "LIBWOLFSSL_SAVE_INFO encountered a non-zero VAR_RESULT") + set(${VAR_OUPUT} "Unknown") + endif() +endfunction() # LIBWOLFSSL_SAVE_INFO + +if(NOT CMAKE_BUILD_EARLY_EXPANSION) + # LIBWOLFSSL_VERSION_GIT_HASH + execute_process(COMMAND ${git_cmd} "rev-parse" "HEAD" OUTPUT_VARIABLE TMP_OUT RESULT_VARIABLE TMP_RES ERROR_QUIET ) + LIBWOLFSSL_SAVE_INFO(LIBWOLFSSL_VERSION_GIT_HASH "${TMP_OUT}" "${TMP_RES}") + + # LIBWOLFSSL_VERSION_GIT_SHORT_HASH + execute_process(COMMAND ${git_cmd} "rev-parse" "--short" "HEAD" OUTPUT_VARIABLE TMP_OUT RESULT_VARIABLE TMP_RES ERROR_QUIET ) + LIBWOLFSSL_SAVE_INFO(LIBWOLFSSL_VERSION_GIT_SHORT_HASH "${TMP_OUT}" "${TMP_RES}") + + # LIBWOLFSSL_VERSION_GIT_HASH_DATE + execute_process(COMMAND ${git_cmd} "show" "--no-patch" "--no-notes" "--pretty=\'\%cd\'" OUTPUT_VARIABLE TMP_OUT RESULT_VARIABLE TMP_RES ) + LIBWOLFSSL_SAVE_INFO(LIBWOLFSSL_VERSION_GIT_HASH_DATE "${TMP_OUT}" "${TMP_RES}") +endif() + +message(STATUS "") + diff --git a/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/main/echoserver.c b/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/main/echoserver.c new file mode 100644 index 000000000..2eae60762 --- /dev/null +++ b/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/main/echoserver.c @@ -0,0 +1,2737 @@ +/* echoserver.c + * + * Copyright (C) 2014-2023 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 . + */ + +#ifdef HAVE_CONFIG_H + #include +#endif + +#define WOLFSSH_TEST_SERVER +#define WOLFSSH_TEST_ECHOSERVER + +#ifdef WOLFSSL_USER_SETTINGS + #include +#else + #include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "echoserver.h" + +#if defined(WOLFSSL_PTHREADS) && defined(WOLFSSL_TEST_GLOBAL_REQ) + #include +#endif + +#if defined(WOLFSSH_SHELL) && defined(USE_WINDOWS_API) +#pragma message ("echoserver with shell on windows is not supported, use wolfSSHd instead") +#undef WOLFSSH_SHELL +#endif + +#if defined(WOLFSSL_NUCLEUS) || defined(WOLFSSH_ZEPHYR) + /* use buffers for keys with server */ + #define NO_FILESYSTEM + #define WOLFSSH_NO_EXIT +#endif + +#ifdef NO_FILESYSTEM + #include +#endif + +#ifdef WOLFSSH_SHELL + #ifdef HAVE_PTY_H + #include + #endif + #ifdef HAVE_UTIL_H + #include + #endif + #ifdef HAVE_TERMIOS_H + #include + #endif +#ifndef USE_WINDOWS_API + #include +#endif + #include +#if defined(__QNX__) || defined(__QNXNTO__) + #include + #include + +#elif defined(USE_WINDOWS_API) + #include +#else + #include +#endif +#endif /* WOLFSSH_SHELL */ + +#ifdef WOLFSSH_AGENT + #include + #include + #include +#endif /* WOLFSSH_AGENT */ + +#ifdef HAVE_SYS_SELECT_H + #include +#endif + +#ifndef USE_WINDOWS_API + #include + #define SOCKET_ERRNO errno + #define SOCKET_ECONNRESET ECONNRESET + #define SOCKET_ECONNABORTED ECONNABORTED + #define SOCKET_EWOULDBLOCK EWOULDBLOCK +#else + #include + #define SOCKET_ERRNO WSAGetLastError() + #define SOCKET_ECONNRESET WSAECONNRESET + #define SOCKET_ECONNABORTED WSAECONNABORTED + #define SOCKET_EWOULDBLOCK WSAEWOULDBLOCK +#endif + + +#ifndef NO_WOLFSSH_SERVER + +static const char echoserverBanner[] = "wolfSSH Example Echo Server\n"; + +static int quit = 0; +wolfSSL_Mutex doneLock; +#define MAX_PASSWD_RETRY 3 +static int passwdRetry = MAX_PASSWD_RETRY; + + +#ifndef EXAMPLE_HIGHWATER_MARK + #define EXAMPLE_HIGHWATER_MARK 0x3FFF8000 /* 1GB - 32kB */ +#endif + +#ifndef EXAMPLE_BUFFER_SZ + #define EXAMPLE_BUFFER_SZ 4096 +#endif + +#ifndef EXAMPLE_KEYLOAD_BUFFER_SZ + #define EXAMPLE_KEYLOAD_BUFFER_SZ 1200 +#endif + + +#ifdef WOLFSSH_AGENT +typedef struct WS_AgentCbActionCtx { + struct sockaddr_un name; + WS_SOCKET_T listenFd; + WS_SOCKET_T fd; + pid_t pid; + int state; +} WS_AgentCbActionCtx; +#endif + + +#ifdef WOLFSSH_FWD +enum FwdStates { + FWD_STATE_INIT, + FWD_STATE_LISTEN, + FWD_STATE_CONNECT, + FWD_STATE_CONNECTED, + FWD_STATE_DIRECT, +}; + +typedef struct WS_FwdCbActionCtx { + void* heap; + char* hostName; + char* originName; + word16 hostPort; + word16 originPort; + WS_SOCKET_T listenFd; + WS_SOCKET_T appFd; + int error; + int state; + int isDirect; + word32 channelId; +} WS_FwdCbActionCtx; +#endif + + +typedef struct { + WOLFSSH* ssh; + WS_SOCKET_T fd; + word32 id; + int echo; + char nonBlock; +#if defined(WOLFSSL_PTHREADS) && defined(WOLFSSL_TEST_GLOBAL_REQ) + WOLFSSH_CTX *ctx; +#endif +#ifdef WOLFSSH_AGENT + WS_AgentCbActionCtx agentCbCtx; + byte agentBuffer[EXAMPLE_BUFFER_SZ]; +#endif +#ifdef WOLFSSH_FWD + WS_FwdCbActionCtx fwdCbCtx; + byte fwdBuffer[EXAMPLE_BUFFER_SZ]; +#endif +#ifdef WOLFSSH_SHELL + byte shellBuffer[EXAMPLE_BUFFER_SZ]; +#endif + byte channelBuffer[EXAMPLE_BUFFER_SZ]; + char statsBuffer[EXAMPLE_BUFFER_SZ]; +} thread_ctx_t; + + +static byte find_char(const byte* str, const byte* buf, word32 bufSz) +{ + const byte* cur; + + while (bufSz) { + cur = str; + while (*cur != '\0') { + if (*cur == *buf) + return *cur; + cur++; + } + buf++; + bufSz--; + } + + return 0; +} + + +static int dump_stats(thread_ctx_t* ctx) +{ + word32 statsSz; + word32 txCount, rxCount, seq, peerSeq; + + wolfSSH_GetStats(ctx->ssh, &txCount, &rxCount, &seq, &peerSeq); + + WSNPRINTF(ctx->statsBuffer, sizeof ctx->statsBuffer, + "Statistics for Thread #%u:\r\n" + " txCount = %u\r\n rxCount = %u\r\n" + " seq = %u\r\n peerSeq = %u\r\n", + ctx->id, txCount, rxCount, seq, peerSeq); + statsSz = (word32)WSTRLEN(ctx->statsBuffer); + + fprintf(stderr, "%s", ctx->statsBuffer); + return wolfSSH_stream_send(ctx->ssh, (byte*)ctx->statsBuffer, statsSz); +} + + +static int process_bytes(thread_ctx_t* threadCtx, + const byte* buffer, word32 bufferSz) +{ + int stop = 0; + byte c; + const byte matches[] = { 0x03, 0x05, 0x06, 0x00 }; + + c = find_char(matches, buffer, bufferSz); + switch (c) { + case 0x03: + stop = 1; + break; + case 0x05: + if (dump_stats(threadCtx) <= 0) + stop = 1; + break; + case 0x06: + if (wolfSSH_TriggerKeyExchange(threadCtx->ssh) != WS_SUCCESS) + stop = 1; + break; + } + return stop; +} + + +#if defined(WOLFSSL_PTHREADS) && defined(WOLFSSL_TEST_GLOBAL_REQ) + +#define SSH_TIMEOUT 10 + +static int callbackReqSuccess(WOLFSSH *ssh, void *buf, word32 sz, void *ctx) +{ + if ((WOLFSSH *)ssh != *(WOLFSSH **)ctx){ + printf("ssh(%x) != ctx(%x)\n", (unsigned int)ssh, + (unsigned int)*(WOLFSSH **)ctx); + return WS_FATAL_ERROR; + } + printf("Global Request Success[%d]: %s\n", sz, sz>0?buf:"No payload"); + return WS_SUCCESS; +} + +static int callbackReqFailure(WOLFSSH *ssh, void *buf, word32 sz, void *ctx) +{ + if ((WOLFSSH *)ssh != *(WOLFSSH **)ctx) + { + printf("ssh(%x) != ctx(%x)\n", (unsigned int)ssh, + (unsigned int)*(WOLFSSH **)ctx); + return WS_FATAL_ERROR; + } + printf("Global Request Failure[%d]: %s\n", sz, sz > 0 ? buf : "No payload"); + return WS_SUCCESS; +} + +static void *global_req(void *ctx) +{ + int ret; + const char str[] = "SampleRequest"; + thread_ctx_t *threadCtx = (thread_ctx_t *)ctx; + byte buf[0]; + + wolfSSH_SetReqSuccess(threadCtx->ctx, callbackReqSuccess); + wolfSSH_SetReqSuccessCtx(threadCtx->ssh, &threadCtx->ssh); /* dummy ctx */ + wolfSSH_SetReqFailure(threadCtx->ctx, callbackReqFailure); + wolfSSH_SetReqFailureCtx(threadCtx->ssh, &threadCtx->ssh); /* dummy ctx */ + + while(1){ + + sleep(SSH_TIMEOUT); + + ret = wolfSSH_global_request(threadCtx->ssh, (const unsigned char *)str, + WSTRLEN(str), 1); + if (ret != WS_SUCCESS) + { + printf("Global Request Failed.\n"); + wolfSSH_shutdown(threadCtx->ssh); + return NULL; + } + + wolfSSH_stream_read(threadCtx->ssh, buf, 0); + if (ret != WS_SUCCESS) + { + printf("wolfSSH_stream_read Failed.\n"); + wolfSSH_shutdown(threadCtx->ssh); + return NULL; + } + } + return NULL; +} + +#endif + + +#ifdef WOLFSSH_AGENT + +static const char EnvNameAuthPort[] = "SSH_AUTH_SOCK"; + +static int wolfSSH_AGENT_DefaultActions(WS_AgentCbAction action, void* vCtx) +{ + WS_AgentCbActionCtx* ctx = (WS_AgentCbActionCtx*)vCtx; + int ret = 0; + + if (action == WOLFSSH_AGENT_LOCAL_SETUP) { + struct sockaddr_un* name = &ctx->name; + size_t size; + + WMEMSET(name, 0, sizeof(struct sockaddr_un)); + ctx->pid = getpid(); + name->sun_family = AF_LOCAL; + + ret = snprintf(name->sun_path, sizeof(name->sun_path), + "/tmp/wolfserver.%d", ctx->pid); + + if (ret == 0) { + name->sun_path[sizeof(name->sun_path) - 1] = '\0'; + size = WSTRLEN(name->sun_path) + + offsetof(struct sockaddr_un, sun_path); + ctx->listenFd = socket(AF_UNIX, SOCK_STREAM, 0); + if (ctx->listenFd == -1) { + ret = -1; + } + } + + if (ret == 0) { + ret = bind(ctx->listenFd, + (struct sockaddr *)name, (socklen_t)size); + } + + if (ret == 0) { + ret = setenv(EnvNameAuthPort, name->sun_path, 1); + } + + if (ret == 0) { + ret = listen(ctx->listenFd, 5); + } + + if (ret == 0) { + ctx->state = AGENT_STATE_LISTEN; + } + else { + ret = WS_AGENT_SETUP_E; + } + } + else if (action == WOLFSSH_AGENT_LOCAL_CLEANUP) { + WCLOSESOCKET(ctx->listenFd); + unlink(ctx->name.sun_path); + unsetenv(EnvNameAuthPort); + } + else + ret = WS_AGENT_INVALID_ACTION; + + return ret; +} + +#endif + + +#ifdef WOLFSSH_FWD + +static WS_SOCKET_T connect_addr(const char* name, word16 port) +{ + WS_SOCKET_T newSocket = -1; + int ret; + struct addrinfo hints, *hint, *hint0 = NULL; + char portStr[6]; + + WMEMSET(&hints, 0, sizeof hints); + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_PASSIVE; + + snprintf(portStr, sizeof portStr, "%u", port); + + ret = getaddrinfo(name, portStr, &hints, &hint0); + if (ret) + return -1; + + for (hint = hint0; hint != NULL; hint = hint->ai_next) { + newSocket = socket(hint->ai_family, + hint->ai_socktype, hint->ai_protocol); + + if (newSocket < 0) + continue; + + if (connect(newSocket, hint->ai_addr, + (WS_SOCKLEN_T)hint->ai_addrlen) < 0) { + WCLOSESOCKET(newSocket); + newSocket = -1; + continue; + } + + break; + } + + freeaddrinfo(hint0); + + return newSocket; +} + + +static int wolfSSH_FwdDefaultActions(WS_FwdCbAction action, void* vCtx, + const char* name, word32 port) +{ + WS_FwdCbActionCtx* ctx = (WS_FwdCbActionCtx*)vCtx; + int ret = 0; + + if (action == WOLFSSH_FWD_LOCAL_SETUP) { + ctx->hostName = WSTRDUP(name, NULL, 0); + ctx->hostPort = port; + ctx->isDirect = 1; + ctx->state = FWD_STATE_DIRECT; + } + else if (action == WOLFSSH_FWD_LOCAL_CLEANUP) { + WCLOSESOCKET(ctx->appFd); + if (ctx->hostName) { + WFREE(ctx->hostName, NULL, 0); + ctx->hostName = NULL; + } + if (ctx->originName) { + WFREE(ctx->originName, NULL, 0); + ctx->originName = NULL; + } + ctx->state = FWD_STATE_INIT; + } + else if (action == WOLFSSH_FWD_REMOTE_SETUP) { + struct sockaddr_in addr; + socklen_t addrSz = 0; + + ctx->hostName = WSTRDUP(name, NULL, 0); + ctx->hostPort = port; + + ctx->listenFd = socket(AF_INET, SOCK_STREAM, 0); + if (ctx->listenFd == -1) { + ret = -1; + } + + if (ret == 0) { + + WMEMSET(&addr, 0, sizeof addr); + if (WSTRCMP(name, "") == 0 || + WSTRCMP(name, "0.0.0.0") == 0 || + WSTRCMP(name, "localhost") == 0 || + WSTRCMP(name, "127.0.0.1") == 0) { + + addr.sin_addr.s_addr = INADDR_ANY; + addr.sin_family = AF_INET; + addr.sin_port = htons((word16)port); + addrSz = sizeof addr; + } + else { + printf("Not using IPv6 yet.\n"); + ret = WS_FWD_SETUP_E; + } + } + + if (ret == 0) { + ret = bind(ctx->listenFd, + (const struct sockaddr*)&addr, addrSz); + } + + if (ret == 0) { + ret = listen(ctx->listenFd, 5); + } + + if (ret == 0) { + ctx->state = FWD_STATE_LISTEN; + } + else { + if (ctx->hostName != NULL) { + WFREE(ctx->hostName, NULL, 0); + ctx->hostName = NULL; + } + if (ctx->listenFd != -1) { + WCLOSESOCKET(ctx->listenFd); + ctx->listenFd = -1; + } + ret = WS_FWD_SETUP_E; + } + } + else if (action == WOLFSSH_FWD_REMOTE_CLEANUP) { + if (ctx->hostName) { + WFREE(ctx->hostName, NULL, 0); + ctx->hostName = NULL; + } + if (ctx->originName) { + WFREE(ctx->originName, NULL, 0); + ctx->originName = NULL; + } + if (ctx->listenFd != -1) { + WCLOSESOCKET(ctx->listenFd); + ctx->listenFd = -1; + } + ctx->state = FWD_STATE_INIT; + } + else if (action == WOLFSSH_FWD_CHANNEL_ID) { + ctx->channelId = port; + } + else + ret = WS_FWD_INVALID_ACTION; + + return ret; +} + +#endif /* WOLFSSH_FWD */ + + +#ifdef SHELL_DEBUG + +static void display_ascii(char *p_buf, + int count) +{ + int i; + + printf(" *"); + for (i = 0; i < count; i++) { + char tmp_char = p_buf[i]; + + if ((isalnum(tmp_char) || ispunct(tmp_char)) && (tmp_char > 0)) + printf("%c", tmp_char); + else + printf("."); + } + printf("*\n"); +} + + +static void buf_dump(unsigned char *buf, int len) +{ + int i; + + printf("\n"); + for (i = 0; issh; + if (ssh == NULL) + return WS_FATAL_ERROR; + + sshFd = wolfSSH_get_fd(ssh); + +#if defined(WOLFSSL_PTHREADS) && defined(WOLFSSL_TEST_GLOBAL_REQ) + /* submit Global Request for keep-alive */ + rc = pthread_create(&globalReq_th, NULL, global_req, threadCtx); + if (rc != 0) + printf("pthread_create() failed.\n"); +#endif + +#ifdef WOLFSSH_SHELL + if (!threadCtx->echo) { + + userName = wolfSSH_GetUsername(ssh); + p_passwd = getpwnam((const char *)userName); + if (p_passwd == NULL) { + /* Not actually a user on the system. */ + #ifdef SHELL_DEBUG + fprintf(stderr, "user %s does not exist\n", userName); + #endif + return WS_FATAL_ERROR; + } + + ChildRunning = 1; + childPid = forkpty(&childFd, NULL, NULL, NULL); + + if (childPid < 0) { + /* forkpty failed, so return */ + ChildRunning = 0; + return WS_FATAL_ERROR; + } + else if (childPid == 0) { + /* Child process */ + const char *args[] = {"-sh", NULL}; + + signal(SIGINT, SIG_DFL); + + #ifdef SHELL_DEBUG + printf("userName is %s\n", userName); + system("env"); + #endif + + setenv("HOME", p_passwd->pw_dir, 1); + setenv("LOGNAME", p_passwd->pw_name, 1); + rc = chdir(p_passwd->pw_dir); + if (rc != 0) { + return WS_FATAL_ERROR; + } + + execv("/bin/sh", (char **)args); + } + } +#endif + { + /* Parent process */ +#ifdef WOLFSSH_SHELL + struct termios tios; +#endif + word32 shellChannelId = 0; +#ifdef WOLFSSH_AGENT + WS_SOCKET_T agentFd = -1; + WS_SOCKET_T agentListenFd = threadCtx->agentCbCtx.listenFd; + word32 agentChannelId = -1; +#endif +#ifdef WOLFSSH_FWD + WS_SOCKET_T fwdFd = -1; + WS_SOCKET_T fwdListenFd = threadCtx->fwdCbCtx.listenFd; + word32 fwdBufferIdx = 0; +#endif + +#ifdef WOLFSSH_SHELL + if (!threadCtx->echo) { + #ifdef SHELL_DEBUG + printf("In childPid > 0; getpid=%d\n", (int)getpid()); + #endif + signal(SIGCHLD, ChildSig); + + rc = tcgetattr(childFd, &tios); + if (rc != 0) { + printf("tcgetattr failed: rc =%d,errno=%x\n", rc, errno); + return WS_FATAL_ERROR; + } + rc = tcsetattr(childFd, TCSAFLUSH, &tios); + if (rc != 0) { + printf("tcsetattr failed: rc =%d,errno=%x\n", rc, errno); + return WS_FATAL_ERROR; + } + + #ifdef SHELL_DEBUG + termios_show(childFd); + #endif + } + else + ChildRunning = 1; +#else + ChildRunning = 1; +#endif + + while (ChildRunning) { + fd_set readFds; + WS_SOCKET_T maxFd; + int cnt_r; + int cnt_w; + + FD_ZERO(&readFds); + FD_SET(sshFd, &readFds); + maxFd = sshFd; + +#ifdef WOLFSSH_SHELL + if (!threadCtx->echo) { + FD_SET(childFd, &readFds); + if (childFd > maxFd) + maxFd = childFd; + } +#endif +#ifdef WOLFSSH_AGENT + if (threadCtx->agentCbCtx.state == AGENT_STATE_LISTEN) { + FD_SET(agentListenFd, &readFds); + if (agentListenFd > maxFd) + maxFd = agentListenFd; + } + if (agentFd >= 0 && threadCtx->agentCbCtx.state == AGENT_STATE_CONNECTED) { + FD_SET(agentFd, &readFds); + if (agentFd > maxFd) + maxFd = agentFd; + } +#endif +#ifdef WOLFSSH_FWD + if (threadCtx->fwdCbCtx.state == FWD_STATE_LISTEN) { + FD_SET(fwdListenFd, &readFds); + if (fwdListenFd > maxFd) + maxFd = fwdListenFd; + } + if (fwdFd >= 0 && threadCtx->fwdCbCtx.state == FWD_STATE_CONNECTED) { + FD_SET(fwdFd, &readFds); + if (fwdFd > maxFd) + maxFd = fwdFd; + } +#endif + rc = select((int)maxFd + 1, &readFds, NULL, NULL, NULL); + if (rc == -1) + break; + + if (FD_ISSET(sshFd, &readFds)) { + word32 lastChannel = 0; + + /* The following tries to read from the first channel inside + the stream. If the pending data in the socket is for + another channel, this will return an error with id + WS_CHAN_RXD. That means the agent has pending data in its + channel. The additional channel is only used with the + agent. */ + cnt_r = wolfSSH_worker(ssh, &lastChannel); + if (cnt_r < 0) { + rc = wolfSSH_get_error(ssh); + if (rc == WS_CHAN_RXD) { + if (lastChannel == shellChannelId) { + cnt_r = wolfSSH_ChannelIdRead(ssh, shellChannelId, + threadCtx->channelBuffer, + sizeof threadCtx->channelBuffer); + if (cnt_r <= 0) + break; + #ifdef SHELL_DEBUG + buf_dump(threadCtx->channelBuffer, cnt_r); + #endif + #ifdef WOLFSSH_SHELL + if (!threadCtx->echo) { + cnt_w = (int)write(childFd, + threadCtx->channelBuffer, cnt_r); + } + else { + cnt_w = wolfSSH_ChannelIdSend(ssh, + shellChannelId, + threadCtx->channelBuffer, cnt_r); + if (cnt_r > 0) { + int doStop = process_bytes(threadCtx, + threadCtx->channelBuffer, + cnt_r); + ChildRunning = !doStop; + } + } + #else + cnt_w = wolfSSH_ChannelIdSend(ssh, shellChannelId, + threadCtx->channelBuffer, cnt_r); + if (cnt_r > 0) { + int doStop = process_bytes(threadCtx, + threadCtx->channelBuffer, cnt_r); + ChildRunning = !doStop; + } + #endif + if (cnt_w <= 0) + break; + } + #ifdef WOLFSSH_AGENT + if (lastChannel == agentChannelId) { + cnt_r = wolfSSH_ChannelIdRead(ssh, agentChannelId, + threadCtx->channelBuffer, + sizeof threadCtx->channelBuffer); + if (cnt_r <= 0) + break; + #ifdef SHELL_DEBUG + buf_dump(threadCtx->channelBuffer, cnt_r); + #endif + cnt_w = (int)send(agentFd, + threadCtx->channelBuffer, cnt_r, 0); + if (cnt_w <= 0) + break; + } + #endif + #ifdef WOLFSSH_FWD + if (threadCtx->fwdCbCtx.state == FWD_STATE_CONNECTED && + lastChannel == threadCtx->fwdCbCtx.channelId) { + + cnt_r = wolfSSH_ChannelIdRead(ssh, + threadCtx->fwdCbCtx.channelId, + threadCtx->channelBuffer, + sizeof threadCtx->channelBuffer); + if (cnt_r <= 0) + break; + #ifdef SHELL_DEBUG + buf_dump(threadCtx->channelBuffer, cnt_r); + #endif + cnt_w = (int)send(fwdFd, threadCtx->channelBuffer, + cnt_r, 0); + if (cnt_w <= 0) + break; + } + #endif + } + else if (rc == WS_CHANNEL_CLOSED) { + #ifdef WOLFSSH_FWD + if (threadCtx->fwdCbCtx.state == FWD_STATE_CONNECTED && + lastChannel == threadCtx->fwdCbCtx.channelId) { + /* Read zero-returned. Socket is closed. Go back + to listening. */ + if (fwdFd != -1) { + WCLOSESOCKET(fwdFd); + fwdFd = -1; + } + if (threadCtx->fwdCbCtx.originName != NULL) { + WFREE(threadCtx->fwdCbCtx.originName, + NULL, 0); + threadCtx->fwdCbCtx.originName = NULL; + } + threadCtx->fwdCbCtx.state = FWD_STATE_LISTEN; + } + #endif + continue; + } + else if (rc != WS_WANT_READ) { + #ifdef SHELL_DEBUG + printf("Break:read sshFd returns %d: errno =%x\n", + cnt_r, errno); + #endif + break; + } + } + } + + #ifdef WOLFSSH_SHELL + if (!threadCtx->echo) { + if (FD_ISSET(childFd, &readFds)) { + cnt_r = (int)read(childFd, + threadCtx->shellBuffer, + sizeof threadCtx->shellBuffer); + /* This read will return 0 on EOF */ + if (cnt_r <= 0) { + int err = errno; + if (err != EAGAIN) { + #ifdef SHELL_DEBUG + printf("Break:read childFd returns %d: " + "errno =%x\n", + cnt_r, err); + #endif + break; + } + } + else { + #ifdef SHELL_DEBUG + buf_dump(threadCtx->shellBuffer, cnt_r); + #endif + if (cnt_r > 0) { + cnt_w = wolfSSH_ChannelIdSend(ssh, shellChannelId, + threadCtx->shellBuffer, cnt_r); + if (cnt_w < 0) + break; + } + } + } + } + #endif + #ifdef WOLFSSH_AGENT + if (agentFd >= 0 && threadCtx->agentCbCtx.state == AGENT_STATE_CONNECTED) { + if (FD_ISSET(agentFd, &readFds)) { + #ifdef SHELL_DEBUG + printf("agentFd set in readfd\n"); + #endif + cnt_r = (int)recv(agentFd, + threadCtx->agentBuffer, + sizeof threadCtx->agentBuffer, 0); + if (cnt_r == 0) { + /* Read zero-returned. Socket is closed. Go back + to listening. */ + threadCtx->agentCbCtx.state = AGENT_STATE_LISTEN; + continue; + } + else if (cnt_r < 0) { + int err = SOCKET_ERRNO; + #ifdef SHELL_DEBUG + printf("Break:read agentFd returns %d: " + "errno = %d\n", cnt_r, err); + #endif + if (err == SOCKET_ECONNRESET || + err == SOCKET_ECONNABORTED) { + /* Connection reset. Socket is closed. + * Go back to listening. */ + threadCtx->agentCbCtx.state = AGENT_STATE_LISTEN; + continue; + } + break; + } + else { + #ifdef SHELL_DEBUG + buf_dump(threadCtx->agentBuffer, cnt_r); + #endif + cnt_w = wolfSSH_ChannelIdSend(ssh, agentChannelId, + threadCtx->agentBuffer, cnt_r); + if (cnt_w <= 0) { + break; + } + } + } + } + if (threadCtx->agentCbCtx.state == AGENT_STATE_LISTEN) { + if (FD_ISSET(agentListenFd, &readFds)) { + #ifdef SHELL_DEBUG + printf("accepting agent connection\n"); + #endif + agentFd = accept(agentListenFd, NULL, NULL); + if (agentFd == -1) { + rc = errno; + if (rc != SOCKET_EWOULDBLOCK) { + break; + } + } + else { + threadCtx->agentCbCtx.state = AGENT_STATE_CONNECTED; + threadCtx->agentCbCtx.fd = agentFd; + } + } + } + #endif + #ifdef WOLFSSH_FWD + if (fwdFd >= 0 && threadCtx->fwdCbCtx.state == FWD_STATE_CONNECTED) { + if (FD_ISSET(fwdFd, &readFds)) { + #ifdef SHELL_DEBUG + printf("fwdFd set in readfd\n"); + #endif + cnt_r = (int)recv(fwdFd, + threadCtx->fwdBuffer + fwdBufferIdx, + sizeof threadCtx->fwdBuffer - fwdBufferIdx, 0); + if (cnt_r == 0) { + /* Read zero-returned. Socket is closed. Go back + to listening. */ + WCLOSESOCKET(fwdFd); + fwdFd = -1; + if (threadCtx->fwdCbCtx.hostName != NULL) { + WFREE(threadCtx->fwdCbCtx.hostName, + NULL, 0); + threadCtx->fwdCbCtx.hostName = NULL; + } + threadCtx->fwdCbCtx.state = FWD_STATE_LISTEN; + continue; + } + else if (cnt_r < 0) { + int err = SOCKET_ERRNO; + + #ifdef SHELL_DEBUG + printf("Break:read fwdFd returns %d: " + "errno = %d\n", cnt_r, err); + #endif + if (err == SOCKET_ECONNRESET || + err == SOCKET_ECONNABORTED) { + /* Connection reset. Socket is closed. + * Go back to listening. */ + WCLOSESOCKET(fwdFd); + threadCtx->fwdCbCtx.state = FWD_STATE_LISTEN; + continue; + } + break; + } + else { + #ifdef SHELL_DEBUG + buf_dump(threadCtx->fwdBuffer, cnt_r); + #endif + fwdBufferIdx += cnt_r; + } + } + if (fwdBufferIdx > 0) { + cnt_w = wolfSSH_ChannelIdSend(ssh, + threadCtx->fwdCbCtx.channelId, + threadCtx->fwdBuffer, fwdBufferIdx); + if (cnt_w > 0) { + fwdBufferIdx = 0; + } + else if (cnt_w == WS_CHANNEL_NOT_CONF || + cnt_w == WS_CHAN_RXD) { + #ifdef SHELL_DEBUG + printf("Waiting for channel open confirmation.\n"); + #endif + } + else { + break; + } + } + } + if (threadCtx->fwdCbCtx.state == FWD_STATE_LISTEN) { + if (FD_ISSET(fwdListenFd, &readFds)) { + #ifdef SHELL_DEBUG + printf("accepting fwd connection\n"); + #endif + fwdFd = accept(fwdListenFd, NULL, NULL); + if (fwdFd == -1) { + rc = errno; + if (rc != SOCKET_EWOULDBLOCK) { + break; + } + } + else { + struct sockaddr_in6 originAddr; + socklen_t originAddrSz; + const char* out = NULL; + char addr[200]; + + threadCtx->fwdCbCtx.state = FWD_STATE_CONNECT; + threadCtx->fwdCbCtx.appFd = fwdFd; + originAddrSz = sizeof originAddr; + WMEMSET(&originAddr, 0, originAddrSz); + if (getpeername(fwdFd, + (struct sockaddr*)&originAddr, + &originAddrSz) == 0) { + + if (originAddr.sin6_family == AF_INET) { + struct sockaddr_in* addr4 = + (struct sockaddr_in*)&originAddr; + out = inet_ntop(AF_INET, + &addr4->sin_addr, + addr, sizeof addr); + } + else if (originAddr.sin6_family == AF_INET6) { + out = inet_ntop(AF_INET6, + &originAddr.sin6_addr, + addr, sizeof addr); + } + } + if (out != NULL) { + threadCtx->fwdCbCtx.originName = + WSTRDUP(addr, NULL, 0); + threadCtx->fwdCbCtx.originPort = + ntohs(originAddr.sin6_port); + } + } + } + } + if (threadCtx->fwdCbCtx.state == FWD_STATE_CONNECT) { + WOLFSSH_CHANNEL* newChannel; + + newChannel = wolfSSH_ChannelFwdNewRemote(ssh, + threadCtx->fwdCbCtx.hostName, + threadCtx->fwdCbCtx.hostPort, + threadCtx->fwdCbCtx.originName, + threadCtx->fwdCbCtx.originPort); + if (newChannel != NULL) { + threadCtx->fwdCbCtx.state = FWD_STATE_CONNECTED; + } + } + if (threadCtx->fwdCbCtx.state == FWD_STATE_DIRECT) { + fwdFd = connect_addr(threadCtx->fwdCbCtx.hostName, + threadCtx->fwdCbCtx.hostPort); + + if (fwdFd > 0) { + threadCtx->fwdCbCtx.state = FWD_STATE_CONNECTED; + } + } + #endif + } +#ifdef WOLFSSH_SHELL + if (!threadCtx->echo) + WCLOSESOCKET(childFd); +#endif + } + +#if defined(WOLFSSL_PTHREADS) && defined(WOLFSSL_TEST_GLOBAL_REQ) + pthread_join(globalReq_th, NULL); +#endif + + return 0; +} + + +#ifdef WOLFSSH_SFTP + +#define TEST_SFTP_TIMEOUT_SHORT 0 +#define TEST_SFTP_TIMEOUT 1 +#define TEST_SFTP_TIMEOUT_LONG 60 + +/* handle SFTP operations + * returns 0 on success + */ +static int sftp_worker(thread_ctx_t* threadCtx) +{ + WOLFSSH* ssh = threadCtx->ssh; + WS_SOCKET_T s; + int ret = WS_SUCCESS; + int error = -1; + int selected; + unsigned char peek_buf[1]; + int timeout = TEST_SFTP_TIMEOUT; + + s = (WS_SOCKET_T)wolfSSH_get_fd(ssh); + + do { + if (wolfSSH_SFTP_PendingSend(ssh)) { + /* Yes, process the SFTP data. */ + ret = wolfSSH_SFTP_read(ssh); + error = wolfSSH_get_error(ssh); + + if (ret == WS_REKEYING) { + timeout = TEST_SFTP_TIMEOUT; + } + else if (error == WS_WINDOW_FULL) { + timeout = TEST_SFTP_TIMEOUT_LONG; + } + else { + timeout = TEST_SFTP_TIMEOUT_SHORT; + } + + if (error == WS_WANT_READ || error == WS_WANT_WRITE || + error == WS_CHAN_RXD || error == WS_REKEYING || + error == WS_WINDOW_FULL) + ret = error; + if (error == WS_WANT_WRITE && wolfSSH_SFTP_PendingSend(ssh)) { + continue; /* no need to spend time attempting to pull data + * if there is still pending sends */ + } + if (error == WS_EOF) { + break; + } + } + + selected = tcp_select(s, timeout); + if (selected == WS_SELECT_ERROR_READY) { + break; + } + else if (selected == WS_SELECT_TIMEOUT) { + timeout = TEST_SFTP_TIMEOUT_LONG; + continue; + } + + if (ret == WS_WANT_READ || ret == WS_WANT_WRITE || + selected == WS_SELECT_RECV_READY) { + ret = wolfSSH_worker(ssh, NULL); + error = wolfSSH_get_error(ssh); + if (ret == WS_REKEYING) { + /* In a rekey, keeping turning the crank. */ + timeout = TEST_SFTP_TIMEOUT; + continue; + } + + if (error == WS_WANT_READ || error == WS_WANT_WRITE || + error == WS_WINDOW_FULL) { + timeout = TEST_SFTP_TIMEOUT; + ret = error; + continue; + } + + if (error == WS_EOF) { + break; + } + if (ret != WS_SUCCESS && ret != WS_CHAN_RXD) { + /* If not successful and no channel data, leave. */ + break; + } + } + + ret = wolfSSH_stream_peek(ssh, peek_buf, sizeof(peek_buf)); + if (ret > 0) { + /* Yes, process the SFTP data. */ + ret = wolfSSH_SFTP_read(ssh); + error = wolfSSH_get_error(ssh); + timeout = (ret == WS_REKEYING) ? + TEST_SFTP_TIMEOUT : TEST_SFTP_TIMEOUT_SHORT; + if (error == WS_WANT_READ || error == WS_WANT_WRITE || + error == WS_CHAN_RXD || error == WS_REKEYING || + error == WS_WINDOW_FULL) + ret = error; + if (error == WS_EOF) + break; + continue; + } + else if (ret == WS_REKEYING) { + timeout = TEST_SFTP_TIMEOUT; + continue; + } + else if (ret < 0) { + error = wolfSSH_get_error(ssh); + if (error == WS_EOF) + break; + } + + if (ret == WS_FATAL_ERROR && error == 0) { + WOLFSSH_CHANNEL* channel = + wolfSSH_ChannelNext(ssh, NULL); + if (channel && wolfSSH_ChannelGetEof(channel)) { + ret = 0; + break; + } + } + + } while (ret != WS_FATAL_ERROR); + + return ret; +} +#endif + +static int NonBlockSSH_accept(WOLFSSH* ssh) +{ + int ret; + int error; + WS_SOCKET_T sockfd; + int select_ret = 0; + + ret = wolfSSH_accept(ssh); + error = wolfSSH_get_error(ssh); + sockfd = (WS_SOCKET_T)wolfSSH_get_fd(ssh); + + while ((ret != WS_SUCCESS + && ret != WS_SCP_COMPLETE && ret != WS_SFTP_COMPLETE) + && (error == WS_WANT_READ || error == WS_WANT_WRITE)) { + + if (error == WS_WANT_READ) + printf("... server would read block\n"); + else if (error == WS_WANT_WRITE) + printf("... server would write block\n"); + + select_ret = tcp_select(sockfd, 1); + if (select_ret == WS_SELECT_RECV_READY || + select_ret == WS_SELECT_ERROR_READY || + error == WS_WANT_WRITE) + { + ret = wolfSSH_accept(ssh); + error = wolfSSH_get_error(ssh); + } + else if (select_ret == WS_SELECT_TIMEOUT) + error = WS_WANT_READ; + else + error = WS_FATAL_ERROR; + } + + return ret; +} + + +static THREAD_RETURN WOLFSSH_THREAD server_worker(void* vArgs) +{ + int ret = 0, error = 0; + thread_ctx_t* threadCtx = (thread_ctx_t*)vArgs; + + passwdRetry = MAX_PASSWD_RETRY; + + if (!threadCtx->nonBlock) + ret = wolfSSH_accept(threadCtx->ssh); + else + ret = NonBlockSSH_accept(threadCtx->ssh); + +#ifdef WOLFSSH_SCP + /* finish off SCP operation */ + if (ret == WS_SCP_INIT) { + if (!threadCtx->nonBlock) + ret = wolfSSH_accept(threadCtx->ssh); + else + ret = NonBlockSSH_accept(threadCtx->ssh); + } +#endif + + switch (ret) { + case WS_SCP_COMPLETE: + printf("scp file transfer completed\n"); + ret = 0; + break; + + #ifdef WOLFSSH_SFTP + case WS_SFTP_COMPLETE: + ret = sftp_worker(threadCtx); + break; + #endif + + case WS_SUCCESS: + ret = ssh_worker(threadCtx); + break; + } + + if (ret == WS_FATAL_ERROR) { + const char* errorStr; + error = wolfSSH_get_error(threadCtx->ssh); + + errorStr = wolfSSH_ErrorToName(error); + + if (error == WS_VERSION_E) { + ret = 0; /* don't break out of loop with version miss match */ + printf("%s\n", errorStr); + } + else if (error == WS_USER_AUTH_E) { + wolfSSH_SendDisconnect(threadCtx->ssh, + WOLFSSH_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE); + ret = 0; /* don't break out of loop with user auth error */ + printf("%s\n", errorStr); + } + else if (error == WS_SOCKET_ERROR_E) { + ret = 0; + printf("%s\n", errorStr); + } + } + + if (error != WS_SOCKET_ERROR_E && error != WS_FATAL_ERROR) { + ret = wolfSSH_shutdown(threadCtx->ssh); + + /* peer hung up, stop shutdown */ + if (ret == WS_SOCKET_ERROR_E) { + ret = 0; + } + + error = wolfSSH_get_error(threadCtx->ssh); + if (error != WS_SOCKET_ERROR_E && + (error == WS_WANT_READ || error == WS_WANT_WRITE)) { + int maxAttempt = 10; /* make 10 attempts max before giving up */ + int attempt; + + for (attempt = 0; attempt < maxAttempt; attempt++) { + ret = wolfSSH_worker(threadCtx->ssh, NULL); + error = wolfSSH_get_error(threadCtx->ssh); + + /* peer succesfully closed down gracefully */ + if (ret == WS_CHANNEL_CLOSED) { + ret = 0; + break; + } + + /* peer hung up, stop shutdown */ + if (ret == WS_SOCKET_ERROR_E) { + ret = 0; + break; + } + + if (error == WS_WANT_READ || error == WS_WANT_WRITE) { + /* Wanting read or wanting write. Clear ret. */ + ret = 0; + } + else { + break; + } + } + + if (attempt == maxAttempt) { + printf("Gave up on gracefull shutdown, closing the socket\n"); + } + } + } + + if (threadCtx->fd != -1) { + WCLOSESOCKET(threadCtx->fd); + threadCtx->fd = -1; + } +#ifdef WOLFSSH_FWD + if (threadCtx->fwdCbCtx.hostName != NULL) { + WFREE(threadCtx->fwdCbCtx.hostName, NULL, 0); + threadCtx->fwdCbCtx.hostName = NULL; + } + if (threadCtx->fwdCbCtx.originName != NULL) { + WFREE(threadCtx->fwdCbCtx.originName, NULL, 0); + threadCtx->fwdCbCtx.originName = NULL; + } +#endif + wolfSSH_free(threadCtx->ssh); + + if (ret != 0) { + fprintf(stderr, "Error [%d] \"%s\" with handling connection.\n", ret, + wolfSSH_ErrorToName(error)); + #ifndef WOLFSSH_NO_EXIT + wc_LockMutex(&doneLock); + quit = 1; + wc_UnLockMutex(&doneLock); + #endif + } + + WFREE(threadCtx, NULL, 0); + + WOLFSSL_RETURN_FROM_THREAD(0); +} + +#ifndef NO_FILESYSTEM +/* set bufSz to size wanted if too small and buf is null */ +static int load_file(const char* fileName, byte* buf, word32* bufSz) +{ + WFILE* file; + word32 fileSz; + word32 readSz; + + if (fileName == NULL) return 0; + + if (WFOPEN(NULL, &file, fileName, "rb") != 0) + return 0; + WFSEEK(NULL, file, 0, WSEEK_END); + fileSz = (word32)WFTELL(NULL, file); + WREWIND(NULL, file); + + if (fileSz > *bufSz) { + if (buf == NULL) + *bufSz = fileSz; + WFCLOSE(NULL, file); + return 0; + } + + readSz = (word32)WFREAD(NULL, buf, 1, fileSz, file); + if (readSz < fileSz) { + WFCLOSE(NULL, file); + return 0; + } + + WFCLOSE(NULL, file); + + return fileSz; +} +#endif /* NO_FILESYSTEM */ + +#ifdef WOLFSSH_NO_ECDSA_SHA2_NISTP256 + #define ECC_PATH "./keys/server-key-ecc-521.der" +#else + #define ECC_PATH "./keys/server-key-ecc.der" +#endif + +/* returns buffer size on success */ +static int load_key(byte isEcc, byte* buf, word32 bufSz) +{ + word32 sz = 0; + +#ifndef NO_FILESYSTEM + const char* bufName; + bufName = isEcc ? ECC_PATH : "./keys/server-key-rsa.der" ; + sz = load_file(bufName, buf, &bufSz); +#else + /* using buffers instead */ + if (isEcc) { + if ((word32)sizeof_ecc_key_der_256 > bufSz) { + return 0; + } + WMEMCPY(buf, ecc_key_der_256, sizeof_ecc_key_der_256); + sz = sizeof_ecc_key_der_256; + } + else { + if ((word32)sizeof_rsa_key_der_2048 > bufSz) { + return 0; + } + WMEMCPY(buf, (byte*)rsa_key_der_2048, sizeof_rsa_key_der_2048); + sz = sizeof_rsa_key_der_2048; + } +#endif + + return sz; +} + + +typedef struct StrList { + const char* str; + struct StrList* next; +} StrList; + + +static StrList* StrListAdd(StrList* list, const char* str) +{ + if (str != NULL) { + StrList* newStr = (StrList*)WMALLOC(sizeof *newStr, NULL, 0); + + if (newStr != NULL) { + newStr->str = str; + newStr->next = list; + list = newStr; + } + } + + return list; +} + +static void StrListFree(StrList* list) +{ + StrList* curStr; + + while (list != NULL) { + curStr = list; + list = list->next; + WFREE(curStr, NULL, 0); + } +} + + +/* Map user names to passwords */ +/* Use arrays for username and p. The password or public key can + * be hashed and the hash stored here. Then I won't need the type. */ +typedef struct PwMap { + byte type; + byte username[32]; + word32 usernameSz; + byte p[WC_SHA256_DIGEST_SIZE]; + struct PwMap* next; +} PwMap; + + +typedef struct PwMapList { + PwMap* head; +} PwMapList; + + +static PwMap* PwMapNew(PwMapList* list, byte type, const byte* username, + word32 usernameSz, const byte* p, word32 pSz) +{ + PwMap* map; + + map = (PwMap*)WMALLOC(sizeof(PwMap), NULL, 0); + if (map != NULL) { + map->type = type; + if (usernameSz >= sizeof(map->username)) + usernameSz = sizeof(map->username) - 1; + WMEMCPY(map->username, username, usernameSz + 1); + map->username[usernameSz] = 0; + map->usernameSz = usernameSz; + + if (type != WOLFSSH_USERAUTH_NONE) { + wc_Sha256Hash(p, pSz, map->p); + } + + map->next = list->head; + list->head = map; + } + + return map; +} + + +static void PwMapListDelete(PwMapList* list) +{ + if (list != NULL) { + PwMap* head = list->head; + + while (head != NULL) { + PwMap* cur = head; + head = head->next; + WMEMSET(cur, 0, sizeof(PwMap)); + WFREE(cur, NULL, 0); + } + } +} + + +static const char samplePasswordBuffer[] = + "jill:upthehill\n" + "jack:fetchapail\n"; + + +#ifndef WOLFSSH_NO_ECC +#ifndef WOLFSSH_NO_ECDSA_SHA2_NISTP256 +static const char samplePublicKeyEccBuffer[] = + "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAA" + "BBBNkI5JTP6D0lF42tbxX19cE87hztUS6FSDoGvPfiU0CgeNSbI+aFdKIzTP5CQEJSvm25" + "qUzgDtH7oyaQROUnNvk= hansel\n" + "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAA" + "BBBKAtH8cqaDbtJFjtviLobHBmjCtG56DMkP6A4M2H9zX2/YCg1h9bYS7WHd9UQDwXO1Hh" + "IZzRYecXh7SG9P4GhRY= gretel\n"; +#elif !defined(WOLFSSH_NO_ECDSA_SHA2_NISTP521) +static const char samplePublicKeyEccBuffer[] = + "ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAA" + "CFBAET/BOzBb9Jx9b52VIHFP4g/uk5KceDpz2M+/Ln9WiDjsMfb4NgNCAB+EMNJUX/TNBL" + "FFmqr7c6+zUH+QAo2qstvQDsReyFkETRB2vZD//nCZfcAe0RMtKZmgtQLKXzSlimUjXBM4" + "/zE5lwE05aXADp88h8nuaT/X4bll9cWJlH0fUykA== hansel\n" + "ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAA" + "CFBAD3gANmzvkxOBN8MYwRBYO6B//7TTCtA2vwG/W5bqiVVxznXWj0xiFrgayApvH7FDpL" + "HiJ8+c1vUsRVEa8PY5QPsgFow+xv0P2WSrRkn4/UUquftPs1ZHPhdr06LjS19ObvWM8xFZ" + "YU6n0i28UWCUR5qE+BCTzZDWYT8V24YD8UhpaYIw== gretel\n"; +#else + #error "Enable an ECC Curve or disable ECC." +#endif +#endif + +#ifndef WOLFSSH_NO_RSA +static const char samplePublicKeyRsaBuffer[] = + "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC9P3ZFowOsONXHD5MwWiCciXytBRZGho" + "MNiisWSgUs5HdHcACuHYPi2W6Z1PBFmBWT9odOrGRjoZXJfDDoPi+j8SSfDGsc/hsCmc3G" + "p2yEhUZUEkDhtOXyqjns1ickC9Gh4u80aSVtwHRnJZh9xPhSq5tLOhId4eP61s+a5pwjTj" + "nEhBaIPUJO2C/M0pFnnbZxKgJlX7t1Doy7h5eXxviymOIvaCZKU+x5OopfzM/wFkey0EPW" + "NmzI5y/+pzU5afsdeEWdiQDIQc80H6Pz8fsoFPvYSG+s4/wz0duu7yeeV1Ypoho65Zr+pE" + "nIf7dO0B8EblgWt+ud+JI8wrAhfE4x hansel\n" + "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCqDwRVTRVk/wjPhoo66+Mztrc31KsxDZ" + "+kAV0139PHQ+wsueNpba6jNn5o6mUTEOrxrz0LMsDJOBM7CmG0983kF4gRIihECpQ0rcjO" + "P6BSfbVTE9mfIK5IsUiZGd8SoE9kSV2pJ2FvZeBQENoAxEFk0zZL9tchPS+OCUGbK4SDjz" + "uNZl/30Mczs73N3MBzi6J1oPo7sFlqzB6ecBjK2Kpjus4Y1rYFphJnUxtKvB0s+hoaadru" + "biE57dK6BrH5iZwVLTQKux31uCJLPhiktI3iLbdlGZEctJkTasfVSsUizwVIyRjhVKmbdI" + "RGwkU38D043AR1h0mUoGCPIKuqcFMf gretel\n"; +#endif + + +#ifdef WOLFSSH_ALLOW_USERAUTH_NONE + +static const char sampleNoneBuffer[] = + "holmes\n" + "watson\n"; + + +static int LoadNoneBuffer(byte* buf, word32 bufSz, PwMapList* list) +{ + char* str = (char*)buf; + char* username; + + /* Each line of none list is in the format + * username\n + * This function modifies the passed-in buffer. */ + + if (list == NULL) + return -1; + + if (buf == NULL || bufSz == 0) + return 0; + + while (*str != 0) { + username = str; + str = WSTRCHR(username, '\n'); + if (str == NULL) { + return -1; + } + *str = 0; + str++; + if (PwMapNew(list, WOLFSSH_USERAUTH_NONE, + (byte*)username, (word32)WSTRLEN(username), + NULL, 0) == NULL ) { + + return -1; + } + } + + return 0; +} + +#endif /* WOLFSSH_ALLOW_USERAUTH_NONE */ + +static int LoadPasswordBuffer(byte* buf, word32 bufSz, PwMapList* list) +{ + char* str = (char*)buf; + char* delimiter; + char* username; + char* password; + + /* Each line of passwd.txt is in the format + * username:password\n + * This function modifies the passed-in buffer. */ + + if (list == NULL) + return -1; + + if (buf == NULL || bufSz == 0) + return 0; + + while (*str != 0) { + delimiter = WSTRCHR(str, ':'); + if (delimiter == NULL) { + return -1; + } + username = str; + *delimiter = 0; + password = delimiter + 1; + str = WSTRCHR(password, '\n'); + if (str == NULL) { + return -1; + } + *str = 0; + str++; + if (PwMapNew(list, WOLFSSH_USERAUTH_PASSWORD, + (byte*)username, (word32)WSTRLEN(username), + (byte*)password, (word32)WSTRLEN(password)) == NULL ) { + + return -1; + } + } + + return 0; +} + + +static int LoadPublicKeyBuffer(byte* buf, word32 bufSz, PwMapList* list) +{ + char* str = (char*)buf; + char* delimiter; + char* end = (char*)buf + bufSz; + byte* publicKey64; + word32 publicKey64Sz; + byte* username; + word32 usernameSz; + byte* publicKey; + word32 publicKeySz; + + /* Each line of passwd.txt is in the format + * ssh-rsa AAAB3BASE64ENCODEDPUBLICKEYBLOB username\n + * This function modifies the passed-in buffer. */ + if (list == NULL) + return -1; + + if (buf == NULL || bufSz == 0) + return 0; + + while (str < end && *str != 0) { + /* Skip the public key type. This example will always be ssh-rsa. */ + delimiter = WSTRCHR(str, ' '); + if (delimiter == NULL) { + return -1; + } + if (str >= end) + break; + str = delimiter + 1; + delimiter = WSTRCHR(str, ' '); + if (delimiter == NULL) { + return -1; + } + publicKey64 = (byte*)str; + *delimiter = 0; + publicKey64Sz = (word32)(delimiter - str); + if (str >= end) + break; + str = delimiter + 1; + delimiter = WSTRCHR(str, '\n'); + if (delimiter == NULL) { + return -1; + } + username = (byte*)str; + *delimiter = 0; + usernameSz = (word32)(delimiter - str); + str = delimiter + 1; + + /* more than enough space for base64 decode + * not using WMALLOC because internal.h is not included for DYNTYPE_* */ + publicKey = (byte*)WMALLOC(publicKey64Sz, NULL, 0); + if (publicKey == NULL) { + fprintf(stderr, "error with WMALLOC\n"); + return -1; + } + publicKeySz = publicKey64Sz; + + if (Base64_Decode(publicKey64, publicKey64Sz, + publicKey, &publicKeySz) != 0) { + + WFREE(publicKey, NULL, 0); + return -1; + } + + #ifdef DEBUG_WOLFSSH + printf("Adding public key for user : %s\n", username); + #endif + + if (PwMapNew(list, WOLFSSH_USERAUTH_PUBLICKEY, + username, usernameSz, + publicKey, publicKeySz) == NULL ) { + + WFREE(publicKey, NULL, 0); + return -1; + } + WFREE(publicKey, NULL, 0); + } + + return 0; +} + + +static int LoadPasswdList(StrList* strList, PwMapList* mapList) +{ + char names[256]; + char* passwd; + int count = 0; + + while (strList) { + WSTRNCPY(names, strList->str, sizeof names - 1); + passwd = WSTRCHR(names, ':'); + if (passwd != NULL) { + *passwd = 0; + passwd++; + + PwMapNew(mapList, WOLFSSH_USERAUTH_PASSWORD, + (byte*)names, (word32)WSTRLEN(names), + (byte*)passwd, (word32)WSTRLEN(passwd)); + } + else { + fprintf(stderr, "Ignoring password: %s\n", names); + } + + strList = strList->next; + count++; + } + + return count; +} + +#ifndef NO_FILESYSTEM +static int LoadPubKeyList(StrList* strList, int format, PwMapList* mapList) +{ + char names[256]; + char* fileName; + byte* buf; + word32 bufSz; + int count = 0; + + while (strList) { + buf = NULL; + bufSz = 0; + + WSTRNCPY(names, strList->str, sizeof names - 1); + fileName = WSTRCHR(names, ':'); + if (fileName != NULL) { + *fileName = 0; + fileName++; + + load_file(fileName, NULL, &bufSz); + buf = (byte*)WMALLOC(bufSz, NULL, 0); + bufSz = load_file(fileName, buf, &bufSz); + if (bufSz > 0) { + if (format == WOLFSSH_FORMAT_SSH) { + const byte* type = NULL; + byte* out = NULL; + word32 typeSz, outSz; + + wolfSSH_ReadKey_buffer(buf, bufSz, WOLFSSH_FORMAT_SSH, + &out, &outSz, &type, &typeSz, NULL); + + (void)type; + (void)typeSz; + + WFREE(buf, NULL, 0); + buf = out; + bufSz = outSz; + } + else if (format == WOLFSSH_FORMAT_PEM) { + byte* out = NULL; + word32 outSz; + + out = (byte*)WMALLOC(bufSz, NULL, 0); + outSz = wc_CertPemToDer(buf, bufSz, out, bufSz, CERT_TYPE); + + WFREE(buf, NULL, 0); + buf = out; + bufSz = outSz; + } + + PwMapNew(mapList, WOLFSSH_USERAUTH_PUBLICKEY, + (byte*)names, (word32)WSTRLEN(names), buf, bufSz); + } + else { + fprintf(stderr, "File error: %s\n", names); + } + } + else { + fprintf(stderr, "Ignoring key: %s\n", names); + } + + WFREE(buf, NULL, 0); + strList = strList->next; + count++; + } + + return count; +} +#endif + +static int wsUserAuthResult(byte res, + WS_UserAuthData* authData, + void* ctx) +{ + printf("In auth result callback, auth = %s\n", + (res == WOLFSSH_USERAUTH_SUCCESS) ? "Success" : "Failure"); + (void)authData; + (void)ctx; + return WS_SUCCESS; +} + + +static int wsUserAuth(byte authType, + WS_UserAuthData* authData, + void* ctx) +{ + PwMapList* list; + PwMap* map; + byte authHash[WC_SHA256_DIGEST_SIZE]; + + if (ctx == NULL) { + fprintf(stderr, "wsUserAuth: ctx not set"); + return WOLFSSH_USERAUTH_FAILURE; + } + + if (authType != WOLFSSH_USERAUTH_PASSWORD && +#ifdef WOLFSSH_ALLOW_USERAUTH_NONE + authType != WOLFSSH_USERAUTH_NONE && +#endif + authType != WOLFSSH_USERAUTH_PUBLICKEY) { + + return WOLFSSH_USERAUTH_FAILURE; + } + + if (authType == WOLFSSH_USERAUTH_PASSWORD) { + wc_Sha256Hash(authData->sf.password.password, + authData->sf.password.passwordSz, + authHash); + } + else if (authType == WOLFSSH_USERAUTH_PUBLICKEY) { + wc_Sha256Hash(authData->sf.publicKey.publicKey, + authData->sf.publicKey.publicKeySz, + authHash); + #if defined(WOLFSSH_CERTS) && !defined(WOLFSSH_NO_FPKI) && \ + defined(WOLFSSL_FPKI) + /* Display FPKI info UUID and FASC-N, getter function for FASC-N and + * UUID are dependent on wolfSSL version newer than 5.3.0 so gatting + * on the macro WOLFSSL_FPKI here too */ + if (authData->sf.publicKey.isCert) { + DecodedCert cert; + byte* uuid = NULL; + word32 fascnSz; + word32 uuidSz; + word32 i; + int ret; + + printf("Peer connected with FPKI certificate\n"); + wc_InitDecodedCert(&cert, authData->sf.publicKey.publicKey, + authData->sf.publicKey.publicKeySz, NULL); + ret = wc_ParseCert(&cert, CERT_TYPE, 0, NULL); + + /* some profiles supported due not require FASC-N */ + if (ret == 0 && + wc_GetFASCNFromCert(&cert, NULL, &fascnSz) == LENGTH_ONLY_E) { + byte* fascn; + + fascn = (byte*)WMALLOC(fascnSz, NULL, 0); + if (fascn != NULL && + wc_GetFASCNFromCert(&cert, fascn, &fascnSz) == 0) { + printf("HEX of FASC-N :"); + for (i = 0; i < fascnSz; i++) + printf("%02X", fascn[i]); + printf("\n"); + } + if (fascn != NULL) + WFREE(fascn, NULL, 0); + } + + /* all profiles supported must have a UUID */ + if (ret == 0) { + ret = wc_GetUUIDFromCert(&cert, NULL, &uuidSz); + if (ret == LENGTH_ONLY_E) { /* expected error value */ + ret = 0; + } + + if (ret == 0 ) { + uuid = (byte*)WMALLOC(uuidSz, NULL, 0); + if (uuid == NULL) { + ret = WS_MEMORY_E; + } + } + + if (ret == 0) { + ret = wc_GetUUIDFromCert(&cert, uuid, &uuidSz); + printf("UUID string : "); + for (i = 0; i < uuidSz; i++) + printf("%c", uuid[i]); + printf("\n"); + } + + if (uuid != NULL) + WFREE(uuid, NULL, 0); + } + + /* failed to at least get UUID string */ + if (ret != 0) { + return WOLFSSH_USERAUTH_INVALID_PUBLICKEY; + } + } + #endif /* WOLFSSH_CERTS && !WOLFSSH_NO_FPKI */ + } + + list = (PwMapList*)ctx; + map = list->head; + + while (map != NULL) { + if (authData->usernameSz == map->usernameSz && + WMEMCMP(authData->username, map->username, map->usernameSz) == 0 && + authData->type == map->type) { + + if (authData->type == WOLFSSH_USERAUTH_PUBLICKEY) { + if (WMEMCMP(map->p, authHash, WC_SHA256_DIGEST_SIZE) == 0) { + return WOLFSSH_USERAUTH_SUCCESS; + } + else { + return WOLFSSH_USERAUTH_INVALID_PUBLICKEY; + } + } + else if (authData->type == WOLFSSH_USERAUTH_PASSWORD) { + if (WMEMCMP(map->p, authHash, WC_SHA256_DIGEST_SIZE) == 0) { + return WOLFSSH_USERAUTH_SUCCESS; + } + else { + passwdRetry--; + return (passwdRetry > 0) ? + WOLFSSH_USERAUTH_INVALID_PASSWORD : + WOLFSSH_USERAUTH_REJECTED; + } + } + #ifdef WOLFSSH_ALLOW_USERAUTH_NONE + else if (authData->type == WOLFSSH_USERAUTH_NONE) { + return WOLFSSH_USERAUTH_SUCCESS; + } + #endif /* WOLFSSH_ALLOW_USERAUTH_NONE */ + else { + return WOLFSSH_USERAUTH_INVALID_AUTHTYPE; + } + } + map = map->next; + } + + return WOLFSSH_USERAUTH_INVALID_USER; +} + + +#ifdef WOLFSSH_SFTP +/* + * Sets the WOLFSSH object's default SFTP path to the value provided by + * defaultSftpPath, or uses the current working directory from where the + * echoserver is run. The new default path is cleaned up with the real + * path function. + * + * @param ssh WOLFSSH object to update + * @param defaultSftpPath command line provided default SFTP path + * @return 0 for success or error code + */ +static int SetDefaultSftpPath(WOLFSSH* ssh, const char* defaultSftpPath) +{ + char path[WOLFSSH_MAX_FILENAME]; + char realPath[WOLFSSH_MAX_FILENAME]; + int ret = 0; + + if (defaultSftpPath == NULL) { + #ifndef NO_FILESYSTEM + #ifdef USE_WINDOWS_API + if (GetCurrentDirectoryA(sizeof(path)-1, path) == 0) { + ret = WS_INVALID_PATH_E; + } + #else + if (getcwd(path, sizeof(path)-1) == NULL) { + ret = WS_INVALID_PATH_E; + } + #endif + #elif defined(WOLFSSH_ZEPHYR) + WSTRNCPY(path, CONFIG_WOLFSSH_SFTP_DEFAULT_DIR, WOLFSSH_MAX_FILENAME); + #else + ret = WS_INVALID_PATH_E; + #endif + } + else { + if (WSTRLEN(defaultSftpPath) >= sizeof(path)) { + ret = WS_INVALID_PATH_E; + } + else { + WSTRNCPY(path, defaultSftpPath, sizeof(path)); + } + } + + if (ret == 0) { + path[sizeof(path) - 1] = 0; + ret = wolfSSH_RealPath(NULL, path, realPath, sizeof(realPath)); + } + + if (ret == WS_SUCCESS) { + ret = wolfSSH_SFTP_SetDefaultPath(ssh, realPath); + } + + return ret; +} +#endif + + +static void ShowUsage(void) +{ + printf("echoserver %s\n", LIBWOLFSSH_VERSION_STRING); + printf(" -? display this help and exit\n"); + printf(" -1 exit after single (one) connection\n"); + printf(" -e expect ECC public key from client\n"); + printf(" -E load ECC private key first\n"); +#ifdef WOLFSSH_SHELL + printf(" -f echo input\n"); +#endif + printf(" -p port to connect on, default %d\n", wolfSshPort); + printf(" -N use non-blocking sockets\n"); +#ifdef WOLFSSH_SFTP + printf(" -d set the home directory for SFTP connections\n"); +#endif + printf(" -j load in a SSH public key to accept from peer\n" + " (user assumed in comment)\n"); + printf(" -I :\n" + " load in a SSH public key to accept from peer\n"); + printf(" -J :\n" + " load in an X.509 PEM cert to accept from peer\n"); + printf(" -K :\n" + " load in an X.509 DER cert to accept from peer\n"); + printf(" -P :\n" + " add password to accept from peer\n"); +#ifdef WOLFSSH_CERTS + printf(" -a load in a root CA certificate file\n"); +#endif +} + + +static INLINE void SignalTcpReady(func_args* serverArgs, word16 port) +{ +#if defined(_POSIX_THREADS) && defined(NO_MAIN_DRIVER) && \ + !defined(__MINGW32__) && !defined(SINGLE_THREADED) + tcp_ready* ready = serverArgs->signal; + if (ready != NULL) { + pthread_mutex_lock(&ready->mutex); + ready->ready = 1; + ready->port = port; + pthread_cond_signal(&ready->cond); + pthread_mutex_unlock(&ready->mutex); + } +#else + (void)serverArgs; + (void)port; +#endif +} + +#define ES_ERROR(...) do { \ + fprintf(stderr, __VA_ARGS__); \ + serverArgs->return_code = EXIT_FAILURE; \ + WOLFSSL_RETURN_FROM_THREAD(0); \ +} while(0) + +THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args) +{ + func_args* serverArgs = (func_args*)args; + WOLFSSH_CTX* ctx = NULL; + PwMapList pwMapList; + #ifndef NO_FILESYSTEM + StrList* sshPubKeyList = NULL; + StrList* pemPubKeyList = NULL; + StrList* derPubKeyList = NULL; + #endif + StrList* passwdList = NULL; + WS_SOCKET_T listenFd = WOLFSSH_SOCKET_INVALID; + word32 defaultHighwater = EXAMPLE_HIGHWATER_MARK; + word32 threadCount = 0; + int multipleConnections = 1; + int userEcc = 0; + int peerEcc = 0; + int echo = 0; + int ch; + word16 port = wolfSshPort; + char* readyFile = NULL; + const char* defaultSftpPath = NULL; + char nonBlock = 0; + #ifndef NO_FILESYSTEM + char* userPubKey = NULL; + #endif + #ifdef WOLFSSH_CERTS + char* caCert = NULL; + #endif + + int argc = serverArgs->argc; + char** argv = serverArgs->argv; + serverArgs->return_code = EXIT_SUCCESS; + + if (argc > 0) { + const char* optlist = "?1a:d:efEp:R:Ni:j:I:J:K:P:"; + myoptind = 0; + while ((ch = mygetopt(argc, argv, optlist)) != -1) { + switch (ch) { + case '?' : + ShowUsage(); + serverArgs->return_code = MY_EX_USAGE; + WOLFSSL_RETURN_FROM_THREAD(0); + + case '1': + multipleConnections = 0; + break; + + case 'a': + #ifdef WOLFSSH_CERTS + caCert = myoptarg; + #endif + break; + case 'e' : + userEcc = 1; + break; + + case 'E': + peerEcc = 1; + break; + + case 'f': + #ifdef WOLFSSH_SHELL + echo = 1; + #endif + break; + + case 'p': + if (myoptarg == NULL) { + ES_ERROR("NULL port value"); + } + else { + port = (word16)atoi(myoptarg); + #if !defined(NO_MAIN_DRIVER) || defined(USE_WINDOWS_API) + if (port == 0) { + ES_ERROR("port number cannot be 0"); + } + #endif + } + break; + + case 'R': + readyFile = myoptarg; + break; + + case 'N': + nonBlock = 1; + break; + + case 'd': + defaultSftpPath = myoptarg; + break; + +#ifndef NO_FILESYSTEM + case 'j': + userPubKey = myoptarg; + break; + + case 'I': + sshPubKeyList = StrListAdd(sshPubKeyList, myoptarg); + break; + + case 'J': + pemPubKeyList = StrListAdd(pemPubKeyList, myoptarg); + break; + + case 'K': + derPubKeyList = StrListAdd(derPubKeyList, myoptarg); + break; +#endif + + case 'P': + passwdList = StrListAdd(passwdList, myoptarg); + break; + + default: + ShowUsage(); + serverArgs->return_code = MY_EX_USAGE; + WOLFSSL_RETURN_FROM_THREAD(0); + } + } + } + myoptind = 0; /* reset for test cases */ + wc_InitMutex(&doneLock); + +#ifdef WOLFSSH_TEST_BLOCK + if (!nonBlock) { + ES_ERROR("Use -N when testing forced non blocking"); + } +#endif + +#ifdef WOLFSSH_NO_RSA + /* If wolfCrypt isn't built with RSA, force ECC on. */ + userEcc = 1; + peerEcc = 1; +#endif +#ifdef WOLFSSH_NO_ECC + /* If wolfCrypt isn't built with ECC, force ECC off. */ + userEcc = 0; + peerEcc = 0; +#endif + (void)userEcc; + + if (wolfSSH_Init() != WS_SUCCESS) { + ES_ERROR("Couldn't initialize wolfSSH.\n"); + } + + ctx = wolfSSH_CTX_new(WOLFSSH_ENDPOINT_SERVER, NULL); + if (ctx == NULL) { + ES_ERROR("Couldn't allocate SSH CTX data.\n"); + } + + WMEMSET(&pwMapList, 0, sizeof(pwMapList)); + if (serverArgs->user_auth == NULL) + wolfSSH_SetUserAuth(ctx, wsUserAuth); + else + wolfSSH_SetUserAuth(ctx, ((func_args*)args)->user_auth); + wolfSSH_SetUserAuthResult(ctx, wsUserAuthResult); + wolfSSH_CTX_SetBanner(ctx, echoserverBanner); +#ifdef WOLFSSH_AGENT + wolfSSH_CTX_set_agent_cb(ctx, wolfSSH_AGENT_DefaultActions, NULL); +#endif +#ifdef WOLFSSH_FWD + wolfSSH_CTX_SetFwdCb(ctx, wolfSSH_FwdDefaultActions, NULL); +#endif + +#ifndef NO_FILESYSTEM + if (sshPubKeyList) { + LoadPubKeyList(sshPubKeyList, WOLFSSH_FORMAT_SSH, &pwMapList); + StrListFree(sshPubKeyList); + sshPubKeyList = NULL; + } + if (pemPubKeyList) { + LoadPubKeyList(pemPubKeyList, WOLFSSH_FORMAT_PEM, &pwMapList); + StrListFree(pemPubKeyList); + pemPubKeyList = NULL; + } + if (derPubKeyList) { + LoadPubKeyList(derPubKeyList, WOLFSSH_FORMAT_ASN1, &pwMapList); + StrListFree(derPubKeyList); + derPubKeyList = NULL; + } +#endif + if (passwdList) { + LoadPasswdList(passwdList, &pwMapList); + StrListFree(passwdList); + passwdList = NULL; + } + + { + const char* bufName = NULL; + #ifndef WOLFSSH_SMALL_STACK + byte buf[EXAMPLE_KEYLOAD_BUFFER_SZ]; + #endif + byte* keyLoadBuf; + word32 bufSz; + + #ifdef WOLFSSH_SMALL_STACK + keyLoadBuf = (byte*)WMALLOC(EXAMPLE_KEYLOAD_BUFFER_SZ, + NULL, 0); + if (keyLoadBuf == NULL) { + ES_ERROR("Error allocating keyLoadBuf"); + } + #else + keyLoadBuf = buf; + #endif + bufSz = EXAMPLE_KEYLOAD_BUFFER_SZ; + + bufSz = load_key(peerEcc, keyLoadBuf, bufSz); + if (bufSz == 0) { + ES_ERROR("Couldn't load first key file.\n"); + } + if (wolfSSH_CTX_UsePrivateKey_buffer(ctx, keyLoadBuf, bufSz, + WOLFSSH_FORMAT_ASN1) < 0) { + ES_ERROR("Couldn't use first key buffer.\n"); + } + + #if !defined(WOLFSSH_NO_RSA) && !defined(WOLFSSH_NO_ECC) + peerEcc = !peerEcc; + bufSz = EXAMPLE_KEYLOAD_BUFFER_SZ; + + bufSz = load_key(peerEcc, keyLoadBuf, bufSz); + if (bufSz == 0) { + ES_ERROR("Couldn't load second key file.\n"); + } + if (wolfSSH_CTX_UsePrivateKey_buffer(ctx, keyLoadBuf, bufSz, + WOLFSSH_FORMAT_ASN1) < 0) { + ES_ERROR("Couldn't use second key buffer.\n"); + } + #endif + + #ifndef NO_FILESYSTEM + if (userPubKey) { + byte* userBuf = NULL; + word32 userBufSz = 0; + + /* get the files size */ + load_file(userPubKey, NULL, &userBufSz); + + /* create temp buffer and load in file */ + if (userBufSz == 0) { + ES_ERROR("Couldn't find size of file %s.\n", userPubKey); + } + + userBuf = (byte*)WMALLOC(userBufSz, NULL, 0); + if (userBuf == NULL) { + ES_ERROR("WMALLOC failed\n"); + } + load_file(userPubKey, userBuf, &userBufSz); + LoadPublicKeyBuffer(userBuf, userBufSz, &pwMapList); + WFREE(userBuf, NULL, 0); + } + #endif + + #ifdef WOLFSSH_CERTS + if (caCert) { + byte* certBuf = NULL; + word32 certBufSz = 0; + int ret = 0; + + load_file(caCert, NULL, &certBufSz); + + if (certBufSz == 0) { + ES_ERROR("Couldn't find size of file %s.\n", caCert); + } + + certBuf = (byte*)WMALLOC(certBufSz, NULL, 0); + if (certBuf == NULL) { + ES_ERROR("WMALLOC failed\n"); + } + load_file(caCert, certBuf, &certBufSz); + ret = wolfSSH_CTX_AddRootCert_buffer(ctx, certBuf, certBufSz, + WOLFSSH_FORMAT_PEM); + if (ret != 0) { + ES_ERROR("Couldn't add root cert\n"); + } + WFREE(certBuf, NULL, 0); + } + #endif + + bufSz = (word32)WSTRLEN(samplePasswordBuffer); + WMEMCPY(keyLoadBuf, samplePasswordBuffer, bufSz); + keyLoadBuf[bufSz] = 0; + LoadPasswordBuffer(keyLoadBuf, bufSz, &pwMapList); + + if (userEcc) { + #ifndef WOLFSSH_NO_ECC + bufName = samplePublicKeyEccBuffer; + #endif + } + else { + #ifndef WOLFSSH_NO_RSA + bufName = samplePublicKeyRsaBuffer; + #endif + } + if (bufName != NULL) { + bufSz = (word32)WSTRLEN(bufName); + WMEMCPY(keyLoadBuf, bufName, bufSz); + keyLoadBuf[bufSz] = 0; + LoadPublicKeyBuffer(keyLoadBuf, bufSz, &pwMapList); + } + + #ifdef WOLFSSH_ALLOW_USERAUTH_NONE + bufSz = (word32)WSTRLEN(sampleNoneBuffer); + WMEMCPY(keyLoadBuf, sampleNoneBuffer, bufSz); + keyLoadBuf[bufSz] = 0; + LoadNoneBuffer(keyLoadBuf, bufSz, &pwMapList); + #endif /* WOLFSSH_ALLOW_USERAUTH_NONE */ + + #ifdef WOLFSSH_SMALL_STACK + WFREE(keyLoadBuf, NULL, 0); + #endif + } +#ifdef WOLFSSL_NUCLEUS + { + int i; + int ret = !NU_SUCCESS; + + /* wait for network and storage device */ + if (NETBOOT_Wait_For_Network_Up(NU_SUSPEND) != NU_SUCCESS) { + ES_ERROR("Couldn't find network.\r\n"); + } + + for(i = 0; i < 15 && ret != NU_SUCCESS; i++) + { + fprintf(stdout, "Checking for storage device\r\n"); + + ret = NU_Storage_Device_Wait(NU_NULL, NU_PLUS_TICKS_PER_SEC); + } + + if (ret != NU_SUCCESS) { + ES_ERROR("Couldn't find storage device.\r\n"); + } + } +#endif + + /* if creating a ready file with port then override port to be 0 */ + if (readyFile != NULL) { + #ifdef NO_FILESYSTEM + ES_ERROR("cannot create readyFile with no file system.\r\n"); + #else + port = 0; + #endif + } + tcp_listen(&listenFd, &port, 1); + /* write out port number listing to, to user set ready file */ + if (readyFile != NULL) { + #ifndef NO_FILESYSTEM + WFILE* f = NULL; + int ret; + ret = WFOPEN(NULL, &f, readyFile, "w"); + if (f != NULL && ret == 0) { + char portStr[10]; + int l = WSNPRINTF(portStr, sizeof(portStr), "%d\n", (int)port); + WFWRITE(NULL, portStr, MIN((size_t)l, sizeof(portStr)), 1, f); + WFCLOSE(NULL, f); + } + #endif + } + + do { + WS_SOCKET_T clientFd = WOLFSSH_SOCKET_INVALID; + #ifdef WOLFSSL_NUCLEUS + struct addr_struct clientAddr; + #else + SOCKADDR_IN_T clientAddr; + socklen_t clientAddrSz = sizeof(clientAddr); + #endif + WOLFSSH* ssh; + thread_ctx_t* threadCtx; + + threadCtx = (thread_ctx_t*)WMALLOC(sizeof(thread_ctx_t), + NULL, 0); + if (threadCtx == NULL) { + ES_ERROR("Couldn't allocate thread context data.\n"); + } + WMEMSET(threadCtx, 0, sizeof *threadCtx); + + ssh = wolfSSH_new(ctx); + if (ssh == NULL) { + WFREE(threadCtx, NULL, 0); + ES_ERROR("Couldn't allocate SSH data.\n"); + } + wolfSSH_SetUserAuthCtx(ssh, &pwMapList); + /* Use the session object for its own highwater callback ctx */ + if (defaultHighwater > 0) { + wolfSSH_SetHighwaterCtx(ssh, (void*)ssh); + wolfSSH_SetHighwater(ssh, defaultHighwater); + } + + #ifdef WOLFSSH_SFTP + if (SetDefaultSftpPath(ssh, defaultSftpPath) != 0) { + ES_ERROR("Couldn't store default sftp path.\n"); + } + #endif + + #ifdef WOLFSSL_NUCLEUS + { + byte ipaddr[MAX_ADDRESS_SIZE]; + char buf[16]; + short addrLength; + struct sockaddr_struct sock; + + addrLength = sizeof(struct sockaddr_struct); + + /* Get the local IP address for the socket. + * 0.0.0.0 if ip adder any */ + if (NU_Get_Sock_Name(listenFd, &sock, &addrLength) != NU_SUCCESS) { + ES_ERROR("Couldn't find network.\r\n"); + } + + WMEMCPY(ipaddr, &sock.ip_num, MAX_ADDRESS_SIZE); + NU_Inet_NTOP(NU_FAMILY_IP, &ipaddr[0], buf, 16); + fprintf(stdout, "Listening on %s:%d\r\n", buf, port); + } + #endif + + SignalTcpReady(serverArgs, port); + + #ifdef WOLFSSL_NUCLEUS + clientFd = NU_Accept(listenFd, &clientAddr, 0); + #else + clientFd = accept(listenFd, (struct sockaddr*)&clientAddr, + &clientAddrSz); + #endif + if (clientFd == -1) { + ES_ERROR("tcp accept failed"); + } + + if (nonBlock) + tcp_set_nonblocking(&clientFd); + + wolfSSH_set_fd(ssh, (int)clientFd); + +#if defined(WOLFSSL_PTHREADS) && defined(WOLFSSL_TEST_GLOBAL_REQ) + threadCtx->ctx = ctx; +#endif + threadCtx->ssh = ssh; + threadCtx->fd = clientFd; + threadCtx->id = threadCount++; + threadCtx->nonBlock = nonBlock; + threadCtx->echo = echo; +#ifdef WOLFSSH_AGENT + wolfSSH_set_agent_cb_ctx(ssh, &threadCtx->agentCbCtx); +#endif +#ifdef WOLFSSH_FWD + threadCtx->fwdCbCtx.state = FWD_STATE_INIT; + threadCtx->fwdCbCtx.listenFd = -1; + threadCtx->fwdCbCtx.appFd = -1; + wolfSSH_SetFwdCbCtx(ssh, &threadCtx->fwdCbCtx); +#endif + server_worker(threadCtx); + + } while (multipleConnections && !quit); + + if (listenFd != WOLFSSH_SOCKET_INVALID) { + WCLOSESOCKET(listenFd); + } + wc_FreeMutex(&doneLock); + PwMapListDelete(&pwMapList); + wolfSSH_CTX_free(ctx); + if (wolfSSH_Cleanup() != WS_SUCCESS) { + ES_ERROR("Couldn't clean up wolfSSH.\n"); + } +#if !defined(WOLFSSH_NO_ECC) && defined(FP_ECC) && defined(HAVE_THREAD_LS) + wc_ecc_fp_free(); /* free per thread cache */ +#endif + + (void)defaultSftpPath; + WOLFSSL_RETURN_FROM_THREAD(0); +} + +#endif /* NO_WOLFSSH_SERVER */ + + +void wolfSSL_Debugging_ON(void); + +int wolfSSH_Echoserver(int argc, char** argv) +{ + func_args args; + + WMEMSET(&args, 0, sizeof(args)); + args.argc = argc; + args.argv = argv; + + WSTARTTCP(); + + #ifdef DEBUG_WOLFSSH + wolfSSL_Debugging_ON(); + wolfSSH_Debugging_ON(); + #endif + +#if !defined(WOLFSSL_NUCLEUS) && !defined(INTEGRITY) && !defined(__INTEGRITY) + ChangeToWolfSshRoot(); +#endif +#ifndef NO_WOLFSSH_SERVER + echoserver_test(&args); +#else + printf("wolfSSH compiled without server support\n"); +#endif + + wolfSSH_Cleanup(); + + return args.return_code; +} + + +#ifndef NO_MAIN_DRIVER + + int main(int argc, char** argv) + { + return wolfSSH_Echoserver(argc, argv); + } + + int myoptind = 0; + char* myoptarg = NULL; + +#endif /* NO_MAIN_DRIVER */ + +#ifdef WOLFSSL_NUCLEUS + + #define WS_TASK_SIZE 200000 + #define WS_TASK_PRIORITY 31 + static NU_TASK serverTask; + + /* expecting void return on main function */ + static VOID main_nucleus(UNSIGNED argc, VOID* argv) + { + main((int)argc, (char**)argv); + } + + + /* using port 8080 because it was an open port on QEMU */ + VOID Application_Initialize (NU_MEMORY_POOL* memPool, + NU_MEMORY_POOL* uncachedPool) + { + void* pt; + int ret; + + UNUSED_PARAMETER(uncachedPool); + + ret = NU_Allocate_Memory(memPool, &pt, WS_TASK_SIZE, NU_NO_SUSPEND); + if (ret == NU_SUCCESS) { + ret = NU_Create_Task(&serverTask, "wolfSSH Server", main_nucleus, 0, + NU_NULL, pt, WS_TASK_SIZE, WS_TASK_PRIORITY, 0, + NU_PREEMPT, NU_START); + if (ret != NU_SUCCESS) { + NU_Deallocate_Memory(pt); + } + } + } +#endif /* WOLFSSL_NUCLEUS */ diff --git a/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/main/include/echoserver.h b/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/main/include/echoserver.h new file mode 100644 index 000000000..ac7e17cf2 --- /dev/null +++ b/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/main/include/echoserver.h @@ -0,0 +1,35 @@ +/* echoserver.h + * + * Copyright (C) 2014-2023 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 . + */ + + +#ifndef _WOLFSSH_EXAMPLES_ECHOSERVER_H_ +#define _WOLFSSH_EXAMPLES_ECHOSERVER_H_ + +#include + +#ifndef WOLFSSH_THREAD + #define WOLFSSH_THREAD +#endif + +THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args); +int wolfSSH_Echoserver(int argc, char** argv); + + +#endif /* _WOLFSSH_EXAMPLES_ECHOSERVER_H_ */ diff --git a/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/main/include/main.h b/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/main/include/main.h new file mode 100644 index 000000000..7e07ec1df --- /dev/null +++ b/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/main/include/main.h @@ -0,0 +1,38 @@ +/* template main.h + * + * Copyright (C) 2006-2023 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL 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 2 of the License, or + * (at your option) any later version. + * + * wolfSSL 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ +#ifndef _MAIN_H_ +#define _MAIN_H_ + +/* Espressif libraries */ +#include "sdkconfig.h" +#include +#include + +/* wolfSSL */ +#include "user_settings.h" /* always include wolfSSL user_settings.h first */ +#include +#include + +/* wolfSSH */ +#include +#include + +#endif diff --git a/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/main/include/time_helper.h b/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/main/include/time_helper.h new file mode 100644 index 000000000..a47f94001 --- /dev/null +++ b/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/main/include/time_helper.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2006-2023 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL 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 2 of the License, or + * (at your option) any later version. + * + * wolfSSL 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/* common Espressif time_helper v5.6.3.001 */ + +#ifndef _TIME_HELPER_H +#define _TIME_HELPER_H + +/* ESP-IDF uses a 64-bit signed integer to represent time_t starting from release v5.0 + * See: https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/system_time.html#year-2036-and-2038-overflow-issues + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* a function to show the current data and time */ +int esp_show_current_datetime(); + +/* worst case, if GitHub time not available, used fixed time */ +int set_fixed_default_time(void); + +/* set time from string (e.g. GitHub commit time) */ +int set_time_from_string(char* time_buffer); + +/* set time from NTP servers, + * also initially calls set_fixed_default_time or set_time_from_string */ +int set_time(void); + +/* wait NTP_RETRY_COUNT seconds before giving up on NTP time */ +int set_time_wait_for_ntp(void); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* #ifndef _TIME_HELPER_H */ diff --git a/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/main/include/wifi_connect.h b/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/main/include/wifi_connect.h new file mode 100644 index 000000000..a0014d4c3 --- /dev/null +++ b/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/main/include/wifi_connect.h @@ -0,0 +1,96 @@ +/* wifi_connect.h + * + * Copyright (C) 2006-2023 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL 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 2 of the License, or + * (at your option) any later version. + * + * wolfSSL 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ +#ifndef _WIFI_CONNECT_H_ +#define _WIFI_CONNECT_H_ + +#include +#include + +/* ESP lwip */ +#define EXAMPLE_ESP_MAXIMUM_RETRY CONFIG_ESP_MAXIMUM_RETRY + +#define TLS_SMP_SERVER_TASK_NAME "tls_sever_example" +#define TLS_SMP_SERVER_TASK_WORDS 22240 +#define TLS_SMP_SERVER_TASK_PRIORITY 8 + +#define TLS_SMP_WIFI_SSID CONFIG_WIFI_SSID +#define TLS_SMP_WIFI_PASS CONFIG_WIFI_PASSWORD + +#define USE_WIFI_EXAMPLE +#ifdef USE_WIFI_EXAMPLE + #include /* see project CMakeLists.txt */ +#endif + +/** + ****************************************************************************** + ****************************************************************************** + ** USER APPLICATION SETTINGS BEGIN + ****************************************************************************** + ****************************************************************************** + **/ + +/* when using a private config with plain text passwords, + * file my_private_config.h should be excluded from git updates */ +/* #define USE_MY_PRIVATE_CONFIG */ + +#ifdef USE_MY_PRIVATE_CONFIG + #if defined(WOLFSSL_CMAKE_SYSTEM_NAME_WINDOWS) + #include "/workspace/my_private_config.h" + #elif defined(WOLFSSL_CMAKE_SYSTEM_NAME_WSL) + #include "/mnt/c/workspace/my_private_config.h" + #elif defined(WOLFSSL_CMAKE_SYSTEM_NAME_LINUX) + #include "~/workspace/my_private_config.h" + #elif defined(WOLFSSL_CMAKE_SYSTEM_NAME_APPLE) + #include "~/Documents/my_private_config.h" + #else + #warning "did not detect environment. using ~/my_private_config.h" + #include "~/my_private_config.h" + #endif +#else + + /* + ** The examples use WiFi configuration that you can set via project + ** configuration menu + ** + ** If you'd rather not, just change the below entries to strings with + ** the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid" + */ + #ifdef CONFIG_ESP_WIFI_SSID + #define EXAMPLE_ESP_WIFI_SSID CONFIG_ESP_WIFI_SSID + #else + #define EXAMPLE_ESP_WIFI_SSID "MYSSID_WIFI_CONNECT" + #endif + + #ifdef CONFIG_ESP_WIFI_PASSWORD + #define EXAMPLE_ESP_WIFI_PASS CONFIG_ESP_WIFI_PASSWORD + #else + #define EXAMPLE_ESP_WIFI_PASS "MYPASSWORD_WIFI_CONNECT" + #endif +#endif + +/* ESP lwip */ +#define EXAMPLE_ESP_MAXIMUM_RETRY CONFIG_ESP_MAXIMUM_RETRY + +int wifi_init_sta(void); + +int wifi_show_ip(void); + +#endif /* _WIFI_CONNECT_H_ */ diff --git a/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/main/main.c b/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/main/main.c new file mode 100644 index 000000000..7781f4281 --- /dev/null +++ b/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/main/main.c @@ -0,0 +1,182 @@ +/* main.c + * + * Copyright (C) 2006-2023 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL 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 2 of the License, or + * (at your option) any later version. + * + * wolfSSL 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ +#include "sdkconfig.h" +#include "main.h" +#include "echoserver.h" + +/* ESP specific */ +#include +#include +#include + +/* wolfSSL */ +#include /* includes wolfSSL user-settings.h */ +#include +#ifndef WOLFSSL_ESPIDF + #warning "Problem with wolfSSL user_settings." + #warning "Check components/wolfssl/include" +#endif + +/* this project */ +#include "wifi_connect.h" +#include "time_helper.h" + +static const char* const TAG = "My Project"; + + +void app_main(void) +{ + void* args = {0}; + int ret = ESP_OK; + + ESP_LOGI(TAG, "------------ wolfSSL wolfSSH template Example ----------"); + ESP_LOGI(TAG, "--------------------------------------------------------"); + ESP_LOGI(TAG, "--------------------------------------------------------"); + ESP_LOGI(TAG, "---------------------- BEGIN MAIN ----------------------"); + ESP_LOGI(TAG, "--------------------------------------------------------"); + ESP_LOGI(TAG, "--------------------------------------------------------"); + + ESP_LOGI(TAG, "Hello wolfSSL!"); + +#ifdef DEBUG_WOLFSSH + wolfSSH_Debugging_ON(); +#else + ESP_LOGI(TAG, "DEBUG_WOLFSSH is not defined, " + "so nothing will happen for the next statement"); +#endif + +#ifdef HAVE_VERSION_EXTENDED_INFO + // esp_ShowExtendedSystemInfo(); +#endif + + /* Set time for cert validation. + * Some lwIP APIs, including SNTP functions, are not thread safe. */ + ret = set_time(); /* need to setup NTP before WiFi */ + ESP_LOGI(TAG, "set_time done."); + + /* Optionally erase flash */ + /* ESP_ERROR_CHECK(nvs_flash_erase()); */ +#ifdef INCLUDE_uxTaskGetStackHighWaterMark + ESP_LOGI(TAG, "Stack HWM: %d", uxTaskGetStackHighWaterMark(NULL)); + + ESP_LOGI(TAG, "Stack used: %d", CONFIG_ESP_MAIN_TASK_STACK_SIZE + - (uxTaskGetStackHighWaterMark(NULL))); +#endif + +/* the simplest check of the wolfSSL library presence: */ +#ifdef LIBWOLFSSL_VERSION_STRING + ESP_LOGI(TAG, ""); + ESP_LOGI(TAG, "Found wolfSSL Version %s\n", LIBWOLFSSL_VERSION_STRING); +#else + ESP_LOGW(TAG, "Warning: Could not find wolfSSL Version"); +#endif + +#ifdef FOUND_PROTOCOL_EXAMPLES_DIR + ESP_LOGI(TAG, "FOUND_PROTOCOL_EXAMPLES_DIR active, using example code."); + ESP_ERROR_CHECK(nvs_flash_init()); + + #if defined(CONFIG_IDF_TARGET_ESP32H2) + ESP_LOGE(TAG, "There's no WiFi on ESP32-H2."); + #else + #ifdef CONFIG_EXAMPLE_WIFI_SSID + if (XSTRCMP(CONFIG_EXAMPLE_WIFI_SSID, "myssid") == 0) { + ESP_LOGW(TAG, "WARNING: CONFIG_EXAMPLE_WIFI_SSID is myssid."); + ESP_LOGW(TAG, " Do you have a WiFi AP called myssid, or "); + ESP_LOGW(TAG, " did you forget the ESP-IDF configuration?"); + } + #else + #define CONFIG_EXAMPLE_WIFI_SSID "myssid" + ESP_LOGW(TAG, "WARNING: CONFIG_EXAMPLE_WIFI_SSID not defined."); + #endif + ESP_ERROR_CHECK(esp_netif_init()); + ESP_ERROR_CHECK(esp_event_loop_create_default()); + ESP_ERROR_CHECK(example_connect()); + #endif +#else + ESP_ERROR_CHECK(nvs_flash_init()); + + /* Initialize NVS */ + ret = nvs_flash_init(); + if (ret == ESP_ERR_NVS_NO_FREE_PAGES || + ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { + ESP_ERROR_CHECK(nvs_flash_erase()); + ret = nvs_flash_init(); + } + ESP_ERROR_CHECK(ret); + + #if defined(CONFIG_IDF_TARGET_ESP32H2) + ESP_LOGE(TAG, "There's no WiFi on ESP32-H2. "); + #else + /* Initialize WiFi */ + ESP_LOGI(TAG, "ESP_WIFI_MODE_STA"); + ret = wifi_init_sta(); + while (ret != 0) { + ESP_LOGI(TAG, "Waiting..."); + vTaskDelay(60000 / portTICK_PERIOD_MS); + ESP_LOGI(TAG, "Trying WiFi again..."); + ret = wifi_init_sta(); + } + #endif +#endif + + /* Once we are connected to the network, start & wait for NTP time */ + // ret = set_time_wait_for_ntp(); + + if (ret < -1) { + /* a value of -1 means there was no NTP server, so no need to wait */ + ESP_LOGI(TAG, "Waiting 10 more seconds for NTP to complete." ); + vTaskDelay(10000 / portTICK_PERIOD_MS); /* brute-force solution */ + esp_show_current_datetime(); + } + + /* HWM is maximum amount of stack space that has been unused, in bytes + * not words (unlike vanilla freeRTOS). */ + ESP_LOGI(TAG, "Initial Stack Used (before wolfSSL Server): %d bytes", + CONFIG_ESP_MAIN_TASK_STACK_SIZE + - (uxTaskGetStackHighWaterMark(NULL)) + ); + ESP_LOGI(TAG, "Starting wolfSSH server_test..."); + + /* TODO: Consider pulling in wolfSSH server.c example source automatically: + * Keep in mind the nature of this example as an Espressif Component. + * See https://github.com/wolfSSL/wolfssh/tree/master/examples/server */ + echoserver_test(&args); + + ESP_LOGI(TAG, "\n\nDone!" + "If running from idf.py monitor, press twice: Ctrl+]"); + + ESP_LOGV(TAG, "\n\nLoop...\n\n"); + ESP_LOGI(TAG, "Stack used: %d", CONFIG_ESP_MAIN_TASK_STACK_SIZE + - uxTaskGetStackHighWaterMark(NULL)); + + while (1) { +#if defined(SINGLE_THREADED) + while (1); +#else + vTaskDelay(60000); +#endif + } + + ESP_LOGI(TAG, "\n\nDone!\n\n" + "If running from idf.py monitor, press twice: Ctrl+]\n\n" + "WOLFSSL_COMPLETE\n" /* exit keyword for wolfssl_monitor.py */ + ); +} /* app_main */ diff --git a/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/main/time_helper.c b/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/main/time_helper.c new file mode 100644 index 000000000..0abf70c5a --- /dev/null +++ b/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/main/time_helper.c @@ -0,0 +1,360 @@ +/* time_helper.c + * + * Copyright (C) 2006-2023 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL 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 2 of the License, or + * (at your option) any later version. + * + * wolfSSL 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/* common Espressif time_helper v5.6.3.002 */ +#include "sdkconfig.h" +#include "time_helper.h" + +#include +#include + +#if defined(ESP_IDF_VERSION_MAJOR) && defined(ESP_IDF_VERSION_MINOR) + #if (ESP_IDF_VERSION_MAJOR == 5) && (ESP_IDF_VERSION_MINOR >= 1) + #define HAS_ESP_NETIF_SNTP 1 + #include + #include + // #include + #else + #include + #include + #endif +#else + /* TODO Consider pre IDF v5? */ +#endif + +/* ESP-IDF uses a 64-bit signed integer to represent time_t starting from release v5.0 + * See: https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/system_time.html#year-2036-and-2038-overflow-issues + */ +const static char* TAG = "time_helper"; + +/* see https://www.gnu.org/software/libc/manual/html_node/TZ-Variable.html */ +#ifndef TIME_ZONE +/* + * PST represents Pacific Standard Time. + * +8 specifies the offset from UTC (Coordinated Universal Time), indicating + * that Pacific Time is UTC-8 during standard time. + * PDT represents Pacific Daylight Time. + * M3.2.0 indicates that Daylight Saving Time (DST) starts on the + * second (2) Sunday (0) of March (3). + * M11.1.0 indicates that DST ends on the first (1) Sunday (0) of November (11) + */ + #define TIME_ZONE "PST+8PDT,M3.2.0,M11.1.0" +#endif /* not defined: TIME_ZONE, so we are setting our own */ + +#define NTP_RETRY_COUNT 10 + +/* NELEMS(x) number of elements + * To determine the number of elements in the array, we can divide the total + * size of the array by the size of the array element. + * See https://stackoverflow.com/questions/37538/how-do-i-determine-the-size-of-my-array-in-c + **/ +#define NELEMS(x) ( (int)(sizeof(x) / sizeof((x)[0])) ) + +/* See also CONFIG_LWIP_SNTP_MAX_SERVERS in sdkconfig */ +#define NTP_SERVER_LIST ( (char*[]) { \ + "pool.ntp.org", \ + "time.nist.gov", \ + "utcnist.colorado.edu" \ + } \ + ) +/* #define NTP_SERVER_COUNT using NELEMS: + * + * (int)(sizeof(NTP_SERVER_LIST) / sizeof(NTP_SERVER_LIST[0])) + */ +#define NTP_SERVER_COUNT NELEMS(NTP_SERVER_LIST) + +#ifndef CONFIG_LWIP_SNTP_MAX_SERVERS + /* We should find max value in sdkconfig, if not set it to our count:*/ + #define CONFIG_LWIP_SNTP_MAX_SERVERS NTP_SERVER_COUNT +#endif + +char* ntpServerList[NTP_SERVER_COUNT] = NTP_SERVER_LIST; + +/* our NTP server list is global info */ +extern char* ntpServerList[NTP_SERVER_COUNT]; + +/* Show the current date and time */ +int esp_show_current_datetime() +{ + time_t now; + char strftime_buf[64]; + struct tm timeinfo; + + time(&now); + setenv("TZ", TIME_ZONE, 1); + tzset(); + + localtime_r(&now, &timeinfo); + strftime(strftime_buf, sizeof(strftime_buf), "%c", &timeinfo); + ESP_LOGI(TAG, "The current date/time is: %s", strftime_buf); + return 0; +} + +/* the worst-case scenario is a hard-coded date/time */ +int set_fixed_default_time(void) +{ + /* ideally, we'd like to set time from network, + * but let's set a default time, just in case */ + struct tm timeinfo = { + .tm_year = 2023 - 1900, + .tm_mon = 10, + .tm_mday = 02, + .tm_hour = 13, + .tm_min = 01, + .tm_sec = 05 + }; + struct timeval now; + time_t interim_time; + int ret = -1; + + /* set interim static time */ + interim_time = mktime(&timeinfo); + + ESP_LOGI(TAG, "Adjusting time from fixed value"); + now = (struct timeval){ .tv_sec = interim_time }; + ret = settimeofday(&now, NULL); + + return ret; +} + +/* set_time_from_string(s) + * + * returns 0 = success if able to set the time from the provided string + * error for any other value, typically -1 */ +int set_time_from_string(char* time_buffer) +{ + /* expecting github default formatting: 'Thu Aug 31 12:41:45 2023 -0700' */ + const char *format = "%3s %3s %d %d:%d:%d %d %s"; + struct tm this_timeinfo; + struct timeval now; + time_t interim_time; + char offset[10]; /* expecting trailing offset and single quote, not used */ + char day_str[4]; + char month_str[4]; + int day, year, hour, minute, second; + int quote_offset = 0; + int ret = 0; + + time(&interim_time); + /* expecting the string to be encapsulated in single quotes */ + if (*time_buffer == 0x27) { + quote_offset = 1; + } + + ret = sscanf(time_buffer + quote_offset, + format, + day_str, month_str, + &day, &hour, &minute, &second, &year, + offset); + + + if (ret == 8) { + /* we found a match for all componets */ + + const char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; + + + /* Ensure day_str and month_str are not too long */ + ret = ESP_FAIL; /* assume failure until proven otherwise */ + this_timeinfo.tm_mon = 0; + if (strlen(day_str) <= 3 && strlen(month_str) <= 3) { + for (int i = 0; i < 12; i++) { + if (strcmp(month_str, months[i]) == 0) { + this_timeinfo.tm_mon = i; + ret = ESP_OK; + break; + } + } + if (ret == ESP_OK) { + this_timeinfo.tm_mday = day; + this_timeinfo.tm_hour = hour; + this_timeinfo.tm_min = minute; + this_timeinfo.tm_sec = second; + this_timeinfo.tm_year = year - 1900; /* years since 1900 */ + + interim_time = mktime(&this_timeinfo); + now = (struct timeval){ .tv_sec = interim_time }; + ret = settimeofday(&now, NULL); + } + else { + ESP_LOGE(TAG, "Bad month value: %s", month_str); + } + + if (ret == ESP_OK) { + ESP_LOGI(TAG, "Time updated to %s", time_buffer); + } + else { + ESP_LOGE(TAG, "Failed to set system time with strig: %s", + time_buffer); + } + } + else { + ESP_LOGE(TAG, "Invalid day (%s) or month (%s) string length.", + day_str, month_str); + ret = ESP_FAIL; + } + } + else { + ESP_LOGE(TAG, "Failed to convert \"%s\" to a tm date.", time_buffer); + ESP_LOGI(TAG, "Trying fixed date that was hard-coded."); + set_fixed_default_time(); + ret = ESP_FAIL; + } + return ret; +} + +/* set time; returns 0 if succecssfully configured with NTP */ +int set_time(void) +{ +#ifndef NTP_SERVER_COUNT + ESP_LOGW(TAG, "Warning: no sntp server names defined. " + "Setting to empty list"); + #define NTP_SERVER_COUNT 0 + #warning "NTP not properly configured" +#endif /* not defined: NTP_SERVER_COUNT */ + +#ifdef HAS_ESP_NETIF_SNTP + #if CONFIG_LWIP_SNTP_MAX_SERVERS > 1 + esp_sntp_config_t config = ESP_NETIF_SNTP_DEFAULT_CONFIG_MULTIPLE( + NTP_SERVER_COUNT, + ESP_SNTP_SERVER_LIST(ntpServerList[0]) + ); + #else + esp_sntp_config_t config = ESP_NETIF_SNTP_DEFAULT_CONFIG(ntpServerList[0]); + #endif /* CONFIG_LWIP_SNTP_MAX_SERVERS > 1 */ +#endif /* HAS_ESP_NETIF_SNTP */ + + int ret = 0; + int i = 0; /* counter for time servers */ + + ESP_LOGI(TAG, "Setting the time. Startup time:"); + esp_show_current_datetime(); + +#ifdef LIBWOLFSSL_VERSION_GIT_HASH_DATE + /* initialy set a default approximate time from recent git commit */ + ESP_LOGI(TAG, "Found git hash date, attempting to set system date."); + set_time_from_string(LIBWOLFSSL_VERSION_GIT_HASH_DATE); + esp_show_current_datetime(); + + ret = -4; +#else + /* otherwise set a fixed time that was hard coded */ + set_fixed_default_time(); + ret = -3; +#endif + +#ifdef CONFIG_SNTP_TIME_SYNC_METHOD_SMOOTH + config.smooth_sync = true; +#endif + + if (NTP_SERVER_COUNT) { + /* next, let's setup NTP time servers + * + * see https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/system_time.html#sntp-time-synchronization + * + * WARNING: do not set operating mode while SNTP client is running! + */ + /* TODO Consider esp_sntp_setoperatingmode(SNTP_OPMODE_POLL); */ + sntp_setoperatingmode(SNTP_OPMODE_POLL); + if (NTP_SERVER_COUNT > CONFIG_LWIP_SNTP_MAX_SERVERS) { + ESP_LOGW(TAG, "WARNING: %d NTP Servers defined, but " + "CONFIG_LWIP_SNTP_MAX_SERVERS = %d", + NTP_SERVER_COUNT,CONFIG_LWIP_SNTP_MAX_SERVERS); + } + ESP_LOGI(TAG, "sntp_setservername:"); + for (i = 0; i < CONFIG_LWIP_SNTP_MAX_SERVERS; i++) { + const char* thisServer = ntpServerList[i]; + if (strncmp(thisServer, "\x00", 1) == 0) { + /* just in case we run out of NTP servers */ + break; + } + ESP_LOGI(TAG, "%s", thisServer); + sntp_setservername(i, thisServer); + } + #ifdef HAS_ESP_NETIF_SNTP + ret = esp_netif_sntp_init(&config); + #else + ESP_LOGW(TAG,"Warning: Consider upgrading ESP-IDF to take advantage " + "of updated SNTP libraries"); + #endif + if (ret == ESP_OK) { + ESP_LOGV(TAG, "Successfully called esp_netif_sntp_init"); + } + else { + ESP_LOGE(TAG, "ERROR: esp_netif_sntp_init return = %d", ret); + } + + sntp_init(); + switch (ret) { + case ESP_ERR_INVALID_STATE: + break; + default: + break; + } + ESP_LOGI(TAG, "sntp_init done."); + } + else { + ESP_LOGW(TAG, "No sntp time servers found."); + ret = -1; + } + return ret; +} + +/* wait for NTP to actually set the time */ +int set_time_wait_for_ntp(void) +{ + int ret = 0; +#ifdef HAS_ESP_NETIF_SNTP + int ntp_retry = 0; + const int ntp_retry_count = NTP_RETRY_COUNT; + + ret = esp_netif_sntp_start(); + + ret = esp_netif_sntp_sync_wait(500 / portTICK_PERIOD_MS); +#endif /* HAS_ESP_NETIF_SNTP */ + esp_show_current_datetime(); + +#ifdef HAS_ESP_NETIF_SNTP + while (ret == ESP_ERR_TIMEOUT && (ntp_retry++ < ntp_retry_count)) { + ret = esp_netif_sntp_sync_wait(1000 / portTICK_PERIOD_MS); + ESP_LOGI(TAG, "Waiting for NTP to sync time... (%d/%d)", + ntp_retry, + ntp_retry_count); + esp_show_current_datetime(); + } +#endif /* HAS_ESP_NETIF_SNTP */ + +#ifdef TIME_ZONE + setenv("TZ", TIME_ZONE, 1); + tzset(); +#endif + + if (ret == ESP_OK) { + ESP_LOGI(TAG, "Successfuly set time via NTP servers."); + } + else { + ESP_LOGW(TAG, "Warning: Failed to set time with NTP: " + "result = 0x%0x: %s", + ret, esp_err_to_name(ret)); + } + return ret; +} diff --git a/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/main/wifi_connect.c b/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/main/wifi_connect.c new file mode 100644 index 000000000..384a86274 --- /dev/null +++ b/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/main/wifi_connect.c @@ -0,0 +1,274 @@ +/* wifi_connect.c + * + * Copyright (C) 2006-2023 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL 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 2 of the License, or + * (at your option) any later version. + * + * wolfSSL 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + #include "wifi_connect.h" + +#include +#include +#include +#include +#include + +/* wolfSSL */ +#include +#include +#include +#ifndef WOLFSSL_ESPIDF + #warning "Problem with wolfSSL user_settings." + #warning "Check components/wolfssl/include" +#endif + +#if ESP_IDF_VERSION_MAJOR >= 5 +#elif ESP_IDF_VERSION_MAJOR >= 4 + #include "protocol_examples_common.h" +#else + const static int CONNECTED_BIT = BIT0; + static EventGroupHandle_t wifi_event_group; +#endif + +#if defined(ESP_IDF_VERSION_MAJOR) && defined(ESP_IDF_VERSION_MINOR) + #if ESP_IDF_VERSION_MAJOR >= 4 + /* likely using examples, see wifi_connect.h */ + #else + /* TODO - still supporting pre V4 ? */ + const static int CONNECTED_BIT = BIT0; + static EventGroupHandle_t wifi_event_group; + #endif + #if (ESP_IDF_VERSION_MAJOR == 5) + #define HAS_WPA3_FEATURES + #else + #undef HAS_WPA3_FEATURES + #endif +#else + /* TODO Consider pre IDF v5? */ +#endif + +/* breadcrumb prefix for logging */ +const static char *TAG = "wifi_connect"; + +#if ESP_IDF_VERSION_MAJOR < 4 +/* event handler for wifi events */ +static esp_err_t wifi_event_handler(void *ctx, system_event_t *event) +{ + switch (event->event_id) + { + case SYSTEM_EVENT_STA_START: + esp_wifi_connect(); + break; + case SYSTEM_EVENT_STA_GOT_IP: + #if ESP_IDF_VERSION_MAJOR >= 4 + ESP_LOGI(TAG, "got ip:" IPSTR "\n", + IP2STR(&event->event_info.got_ip.ip_info.ip)); + #else + ESP_LOGI(TAG, "got ip:%s", + ip4addr_ntoa(&event->event_info.got_ip.ip_info.ip)); + #endif + /* see https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/freertos_idf.html */ + xEventGroupSetBits(wifi_event_group, CONNECTED_BIT); + break; + case SYSTEM_EVENT_STA_DISCONNECTED: + esp_wifi_connect(); + xEventGroupClearBits(wifi_event_group, CONNECTED_BIT); + break; + default: + break; + } + return ESP_OK; +} +#else + +#ifdef CONFIG_ESP_MAXIMUM_RETRY + #define EXAMPLE_ESP_MAXIMUM_RETRY CONFIG_ESP_MAXIMUM_RETRY +#else + #define CONFIG_ESP_MAXIMUM_RETRY 5 +#endif + +#if CONFIG_ESP_WIFI_AUTH_OPEN +#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_OPEN +#elif CONFIG_ESP_WIFI_AUTH_WEP +#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WEP +#elif CONFIG_ESP_WIFI_AUTH_WPA_PSK +#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA_PSK +#elif CONFIG_ESP_WIFI_AUTH_WPA2_PSK +#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA2_PSK +#elif CONFIG_ESP_WIFI_AUTH_WPA_WPA2_PSK +#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA_WPA2_PSK +#elif CONFIG_ESP_WIFI_AUTH_WPA3_PSK +#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA3_PSK +#elif CONFIG_ESP_WIFI_AUTH_WPA2_WPA3_PSK +#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA2_WPA3_PSK +#elif CONFIG_ESP_WIFI_AUTH_WAPI_PSK +#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WAPI_PSK +#endif + +#ifndef ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD + #define CONFIG_ESP_WIFI_AUTH_WPA2_PSK 1 + #define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD CONFIG_ESP_WIFI_AUTH_WPA2_PSK +#endif + +/* FreeRTOS event group to signal when we are connected*/ +static EventGroupHandle_t s_wifi_event_group; + +/* The event group allows multiple bits for each event, but we only care about two events: + * - we are connected to the AP with an IP + * - we failed to connect after the maximum amount of retries */ +#define WIFI_CONNECTED_BIT BIT0 +#define WIFI_FAIL_BIT BIT1 + + +static int s_retry_num = 0; +ip_event_got_ip_t* event; + +static void event_handler(void* arg, + esp_event_base_t event_base, + int32_t event_id, + void* event_data) +{ + if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) { + esp_wifi_connect(); + } + else if (event_base == WIFI_EVENT && + event_id == WIFI_EVENT_STA_DISCONNECTED) { + if (s_retry_num < EXAMPLE_ESP_MAXIMUM_RETRY) { + esp_wifi_connect(); + s_retry_num++; + ESP_LOGI(TAG, "retry to connect to the AP"); + } + else { + xEventGroupSetBits(s_wifi_event_group, WIFI_FAIL_BIT); + } + ESP_LOGI(TAG, "connect to the AP fail"); + } + else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) { + event = (ip_event_got_ip_t*) event_data; + wifi_show_ip(); + s_retry_num = 0; + xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT); + } +} + +int wifi_init_sta(void) +{ + int ret = ESP_OK; + + s_wifi_event_group = xEventGroupCreate(); + + ESP_ERROR_CHECK(esp_netif_init()); + + ESP_ERROR_CHECK(esp_event_loop_create_default()); + esp_netif_create_default_wifi_sta(); + + wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); + ESP_ERROR_CHECK(esp_wifi_init(&cfg)); + + esp_event_handler_instance_t instance_any_id; + esp_event_handler_instance_t instance_got_ip; + ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT, + ESP_EVENT_ANY_ID, + &event_handler, + NULL, + &instance_any_id)); + ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT, + IP_EVENT_STA_GOT_IP, + &event_handler, + NULL, + &instance_got_ip)); + + wifi_config_t wifi_config = { + .sta = { + .ssid = EXAMPLE_ESP_WIFI_SSID, + .password = EXAMPLE_ESP_WIFI_PASS, + /* Authmode threshold resets to WPA2 as default if password matches + * WPA2 standards (pasword len => 8). If you want to connect the + * device to deprecated WEP/WPA networks, Please set the threshold + * value WIFI_AUTH_WEP/WIFI_AUTH_WPA_PSK and set the password with + * length and format matching to WIFI_AUTH_WEP/WIFI_AUTH_WPA_PSK + * standards. */ + .threshold.authmode = ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD, + #ifdef HAS_WPA3_FEATURES + .sae_pwe_h2e = WPA3_SAE_PWE_BOTH, + #endif + }, + }; + ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) ); + ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config) ); + +#ifdef CONFIG_EXAMPLE_WIFI_SSID + if (XSTRCMP(CONFIG_EXAMPLE_WIFI_SSID, "myssid") == 0) { + ESP_LOGW(TAG, "WARNING: CONFIG_EXAMPLE_WIFI_SSID is \"myssid\"."); + ESP_LOGW(TAG, " Do you have a WiFi AP called \"myssid\", "); + ESP_LOGW(TAG, " or did you forget the ESP-IDF configuration?"); + } +#else + ESP_LOGW(TAG, "WARNING: CONFIG_EXAMPLE_WIFI_SSID not defined."); +#endif + + ESP_ERROR_CHECK(esp_wifi_start() ); + + ESP_LOGI(TAG, "wifi_init_sta finished."); + + /* Waiting until either the connection is established (WIFI_CONNECTED_BIT) + * or connection failed for the maximum number of re-tries (WIFI_FAIL_BIT). + * The bits are set by event_handler() (see above) */ + EventBits_t bits = xEventGroupWaitBits(s_wifi_event_group, + WIFI_CONNECTED_BIT | WIFI_FAIL_BIT, + pdFALSE, + pdFALSE, + portMAX_DELAY); + + /* xEventGroupWaitBits() returns the bits before the call returned, + * hence we can test which event actually happened. */ +#if defined(SHOW_SSID_AND_PASSWORD) + ESP_LOGW(TAG, "Undefine SHOW_SSID_AND_PASSWORD to not show SSID/password"); + if (bits & WIFI_CONNECTED_BIT) { + ESP_LOGI(TAG, "connected to ap SSID:%s password:%s", + EXAMPLE_ESP_WIFI_SSID, + EXAMPLE_ESP_WIFI_PASS); + } + else if (bits & WIFI_FAIL_BIT) { + ESP_LOGI(TAG, "Failed to connect to SSID:%s, password:%s", + EXAMPLE_ESP_WIFI_SSID, + EXAMPLE_ESP_WIFI_PASS); + } + else { + ESP_LOGE(TAG, "UNEXPECTED EVENT"); + } +#else + if (bits & WIFI_CONNECTED_BIT) { + ESP_LOGI(TAG, "Connected to AP"); + } + else if (bits & WIFI_FAIL_BIT) { + ESP_LOGI(TAG, "Failed to connect to AP"); + ret = -1; + } + else { + ESP_LOGE(TAG, "AP UNEXPECTED EVENT"); + ret = -2; + } +#endif + return ret; +} + +int wifi_show_ip(void) +{ + // TODO Causes panic: ESP_LOGI(TAG, "got ip:" IPSTR, IP2STR(&event->ip_info.ip)); + return ESP_OK; +} +#endif diff --git a/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/partitions_singleapp_large.csv b/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/partitions_singleapp_large.csv new file mode 100644 index 000000000..a9c373bec --- /dev/null +++ b/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/partitions_singleapp_large.csv @@ -0,0 +1,31 @@ +# to view: idf.py partition-table +# +# ESP-IDF Partition Table +# Name, Type, SubType, Offset, Size, Flags +nvs, data, nvs, 0x9000, 24K, +phy_init,data, phy, 0xf000, 4K, +factory, app, factory, 0x10000, 1500K, + + +# For other settings, see: +# https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/partition-tables.html#creating-custom-tables +# +# Here is the summary printed for the "Single factory app, no OTA" configuration: +# +# # ESP-IDF Partition Table +# # Name, Type, SubType, Offset, Size, Flags +# nvs, data, nvs, 0x9000, 0x6000, +# phy_init, data, phy, 0xf000, 0x1000, +# factory, app, factory, 0x10000, 1M, +# +# +# Here is the summary printed for the "Factory app, two OTA definitions" configuration: +# +# # ESP-IDF Partition Table +# # Name, Type, SubType, Offset, Size, Flags +# nvs, data, nvs, 0x9000, 0x4000, +# otadata, data, ota, 0xd000, 0x2000, +# phy_init, data, phy, 0xf000, 0x1000, +# factory, app, factory, 0x10000, 1M, +# ota_0, app, ota_0, 0x110000, 1M, +# ota_1, app, ota_1, 0x210000, 1M, diff --git a/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/sdkconfig.defaults b/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/sdkconfig.defaults new file mode 100644 index 000000000..5cda514a9 --- /dev/null +++ b/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/sdkconfig.defaults @@ -0,0 +1,38 @@ +# This file was generated using idf.py save-defconfig. It can be edited manually. +# Espressif IoT Development Framework (ESP-IDF) Project Minimal Configuration + +CONFIG_FREERTOS_HZ=1000 +CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y + +# +# Default main stack size +# +# This is typically way bigger than needed for stack size. See user_settings.h +# +CONFIG_ESP_MAIN_TASK_STACK_SIZE=55500 + +# Legacy stack size for older ESP-IDF versions +CONFIG_MAIN_TASK_STACK_SIZE=55500 + +# +# Compiler options +# +CONFIG_COMPILER_OPTIMIZATION_DEFAULT=y +CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE=y +CONFIG_COMPILER_OPTIMIZATION_ASSERTION_LEVEL=2 +CONFIG_COMPILER_HIDE_PATHS_MACROS=y +CONFIG_COMPILER_STACK_CHECK_MODE_NORM=y +CONFIG_COMPILER_STACK_CHECK=y + +# +# Partition Table +# +# CONFIG_PARTITION_TABLE_SINGLE_APP is not set +CONFIG_PARTITION_TABLE_SINGLE_APP_LARGE=y +# CONFIG_PARTITION_TABLE_TWO_OTA is not set +# CONFIG_PARTITION_TABLE_CUSTOM is not set +CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" +CONFIG_PARTITION_TABLE_FILENAME="partitions_singleapp_large.csv" +CONFIG_PARTITION_TABLE_OFFSET=0x8000 +CONFIG_PARTITION_TABLE_MD5=y +# end of Partition Table diff --git a/ide/Espressif/ESP-IDF/examples/wolfssh_template/CMakeLists.txt b/ide/Espressif/ESP-IDF/examples/wolfssh_template/CMakeLists.txt new file mode 100644 index 000000000..58fa04c86 --- /dev/null +++ b/ide/Espressif/ESP-IDF/examples/wolfssh_template/CMakeLists.txt @@ -0,0 +1,83 @@ +# wolfSSL Espressif Example Project CMakeLists.txt +# v1.0 +# +# The following lines of boilerplate have to be in your project's +# CMakeLists in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.16) + +# enable wolfssl user_settings.h project-wide +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DWOLFSSL_USER_SETTINGS") +set(WOLFSSL_USER_SETTINGS ON) + + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DWOLFSSH_TERM") +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DDEBUG_WOLFSSH") + +# The wolfSSL CMake file should be able to find the source code. +# Otherwise, assign an environment variable or set it here: +# +# set(WOLFSSL_ROOT "~/workspace/wolfssl-other-source") +# set(WOLFSSH_ROOT "~/workspace/wolfssh-other-source") +# set(WOLFSSL_ROOT "C:/workspace/wolfssl-master") + +# Optional WOLFSSL_CMAKE_SYSTEM_NAME detection to find +# USE_MY_PRIVATE_CONFIG path for my_private_config.h +# +# Expected path varies: +# +# WSL: /mnt/c/workspace +# Linux: ~/workspace +# Windows: C:\workspace +# +if(WIN32) + # Windows-specific configuration here + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DWOLFSSL_CMAKE_SYSTEM_NAME_WINDOWS") + message("Detected Windows") +endif() +if(CMAKE_HOST_UNIX) + message("Detected UNIX") +endif() +if(APPLE) + message("Detected APPLE") +endif() +if(CMAKE_HOST_UNIX AND (NOT APPLE) AND EXISTS "/proc/sys/fs/binfmt_misc/WSLInterop") + # Windows-specific configuration here + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DWOLFSSL_CMAKE_SYSTEM_NAME_WSL") + message("Detected WSL") +endif() +if(CMAKE_HOST_UNIX AND (NOT APPLE) AND (NOT WIN32)) + # Windows-specific configuration here + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DWOLFSSL_CMAKE_SYSTEM_NAME_LINUX") + message("Detected Linux") +endif() +if(APPLE) + # Windows-specific configuration here + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DWOLFSSL_CMAKE_SYSTEM_NAME_APPLE") + message("Detected Apple") +endif() +# End optional WOLFSSL_CMAKE_SYSTEM_NAME + +# Check that there are not conflicting wolfSSL components +# The ESP Registry Component will be in ./managed_components/wolfssl__wolfssl +# The local component wolfSSL directory will be in ./components/wolfssl +if( EXISTS "${CMAKE_HOME_DIRECTORY}/managed_components/wolfssl__wolfssl" AND EXISTS "${CMAKE_HOME_DIRECTORY}/components/wolfssl" ) + # These exclude statements don't seem to be honored by the $ENV{IDF_PATH}/tools/cmake/project.cmake' + # add_subdirectory("${CMAKE_HOME_DIRECTORY}/managed_components/wolfssl__wolfssl" EXCLUDE_FROM_ALL) + # add_subdirectory("${CMAKE_HOME_DIRECTORY}/managed_components/wolfssl__wolfssl/include" EXCLUDE_FROM_ALL) + # So we'll error out and let the user decide how to proceed: + message(WARNING "\nFound wolfSSL components in\n" + "./managed_components/wolfssl__wolfssl\n" + "and\n" + "./components/wolfssl\n" + "in project directory: \n" + "${CMAKE_HOME_DIRECTORY}") + message(FATAL_ERROR "\nPlease use either the ESP Registry Managed Component or the wolfSSL component directory but not both.\n" + "If removing the ./managed_components/wolfssl__wolfssl directory, remember to also remove " + "or rename the idf_component.yml file typically found in ./main/") +else() + message(STATUS "No conflicting wolfSSL components found.") +endif() + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) + +project(wolfssh_template) diff --git a/ide/Espressif/ESP-IDF/examples/wolfssh_template/README.md b/ide/Espressif/ESP-IDF/examples/wolfssh_template/README.md new file mode 100644 index 000000000..d6dd17ff7 --- /dev/null +++ b/ide/Espressif/ESP-IDF/examples/wolfssh_template/README.md @@ -0,0 +1,64 @@ +# wolfSSL Template Project + +This is an example minimally viable wolfSSL template to get started with your own project. + +### Prerequisites + +It is assumed the [ESP-IDF environment](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/) has been installed. + +### Files Included + +- [main.c](./main/main.c) with a simple call to an Espressif library (`ESP_LOGI`) and a call to a wolfSSL library (`esp_ShowExtendedSystemInfo`) . + +- See [components/wolfssl/include](./components/wolfssl/include/user_settings.h) directory to edit the wolfSSL `user_settings.h`. + +- Edit [main/CMakeLists.txt](./main/CMakeLists.txt) to add/remove source files. + +- The [components/wolfssl/CMakeLists.txt](./components/wolfssl/CMakeLists.txt) typically does not need to be changed. + +- Optional [VisualGDB Project](./VisualGDB/wolfssl_template_IDF_v5.1_ESP32.vgdbproj) for Visual Studio using ESP32 and ESP-IDF v5.1. + +- Edit the project [CMakeLists.txt](./CMakeLists.txt) to optionally point this project's wolfSSL component source code at a different directory: + +``` +set(WOLFSSL_ROOT "~/workspace/wolfssl-other-source") +``` + + +## Getting Started: + +Here's an example using the command-line [idf.py](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/tools/idf-py.html). + +Edit your `WRK_IDF_PATH`to point to your ESP-IDF install directory. + +``` +WRK_IDF_PATH=/mnt/c/SysGCC/esp32/esp-idf/v5.1 + +echo "Run export.sh from ${WRK_IDF_PATH}" +. ${WRK_IDF_PATH}/export.sh + +# build the example: +idf.py build + +# flash the code onto the serial device at /dev/ttyS19 +idf.py flash -p /dev/ttyS19 -b 115200 + +# build, flash, and view UART output with one command: +idf.py flash -p /dev/ttyS19 -b 115200 monitor +``` + +Press `Ctrl+]` to exit `idf.py monitor`. See [additional monitor keyboard commands](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/tools/idf-monitor.html). + +## Other Examples: + +For examples, see: + +- [TLS Client](../wolfssl_client/README.md) +- [TLS Server](../wolfssl_server/README.md) +- [Benchmark](../wolfssl_benchmark/README.md) +- [Test](../wolfssl_test/README.md) +- [wolfssl-examples](https://github.com/wolfSSL/wolfssl-examples/tree/master/ESP32) +- [wolfssh-examples](https://github.com/wolfSSL/wolfssh-examples/tree/main/Espressif) + + + diff --git a/ide/Espressif/ESP-IDF/examples/wolfssh_template/VisualGDB/wolfssh_template_IDF_v5.1_ESP32.sln b/ide/Espressif/ESP-IDF/examples/wolfssh_template/VisualGDB/wolfssh_template_IDF_v5.1_ESP32.sln new file mode 100644 index 000000000..1396c1884 --- /dev/null +++ b/ide/Espressif/ESP-IDF/examples/wolfssh_template/VisualGDB/wolfssh_template_IDF_v5.1_ESP32.sln @@ -0,0 +1,54 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.6.33829.357 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{803FD0C6-D64E-4E16-9DC3-1DAEC859A3D2}") = "wolfssh_template_IDF_v5.1_ESP32", "wolfssh_template_IDF_v5.1_ESP32.vgdbproj", "{EADCC9AB-72B3-4B51-A838-593E5D80DDF7}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{F0564364-33CD-468B-8514-D6A907B2449C}" + ProjectSection(SolutionItems) = preProject + ..\README.md = ..\README.md + ..\..\..\setup.sh = ..\..\..\setup.sh + ..\..\..\setup_win.bat = ..\..\..\setup_win.bat + ..\..\wolfssl_monitor.py = ..\..\wolfssl_monitor.py + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "wolfssh", "wolfssh", "{A9456F78-BEB7-4057-8015-E5A63CB41D44}" + ProjectSection(SolutionItems) = preProject + ..\components\wolfssh\CMakeLists.txt = ..\components\wolfssh\CMakeLists.txt + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "wolfssl", "wolfssl", "{530EF870-BCA9-4320-AD27-1D8FC6B3770C}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "include", "include", "{C3B90A14-D318-4828-BDD3-A5D018C032F5}" + ProjectSection(SolutionItems) = preProject + ..\components\wolfssl\include\user_settings.h = ..\components\wolfssl\include\user_settings.h + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|VisualGDB = Debug|VisualGDB + Release|VisualGDB = Release|VisualGDB + Tests (Debug)|VisualGDB = Tests (Debug)|VisualGDB + Tests (Release)|VisualGDB = Tests (Release)|VisualGDB + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {EADCC9AB-72B3-4B51-A838-593E5D80DDF7}.Debug|VisualGDB.ActiveCfg = Debug|VisualGDB + {EADCC9AB-72B3-4B51-A838-593E5D80DDF7}.Debug|VisualGDB.Build.0 = Debug|VisualGDB + {EADCC9AB-72B3-4B51-A838-593E5D80DDF7}.Release|VisualGDB.ActiveCfg = Release|VisualGDB + {EADCC9AB-72B3-4B51-A838-593E5D80DDF7}.Release|VisualGDB.Build.0 = Release|VisualGDB + {EADCC9AB-72B3-4B51-A838-593E5D80DDF7}.Tests (Debug)|VisualGDB.ActiveCfg = Tests (Debug)|VisualGDB + {EADCC9AB-72B3-4B51-A838-593E5D80DDF7}.Tests (Debug)|VisualGDB.Build.0 = Tests (Debug)|VisualGDB + {EADCC9AB-72B3-4B51-A838-593E5D80DDF7}.Tests (Release)|VisualGDB.ActiveCfg = Tests (Release)|VisualGDB + {EADCC9AB-72B3-4B51-A838-593E5D80DDF7}.Tests (Release)|VisualGDB.Build.0 = Tests (Release)|VisualGDB + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {C3B90A14-D318-4828-BDD3-A5D018C032F5} = {530EF870-BCA9-4320-AD27-1D8FC6B3770C} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {68907C18-A199-469F-8856-F03632FDA03E} + EndGlobalSection +EndGlobal diff --git a/ide/Espressif/ESP-IDF/examples/wolfssh_template/VisualGDB/wolfssh_template_IDF_v5.1_ESP32.vgdbproj b/ide/Espressif/ESP-IDF/examples/wolfssh_template/VisualGDB/wolfssh_template_IDF_v5.1_ESP32.vgdbproj new file mode 100644 index 000000000..9edbb41e2 --- /dev/null +++ b/ide/Espressif/ESP-IDF/examples/wolfssh_template/VisualGDB/wolfssh_template_IDF_v5.1_ESP32.vgdbproj @@ -0,0 +1,269 @@ + + + + + + Unknown + + true + + 7bbd1486-d457-4e49-92ba-0cfc9d80849e + true + true + SourceDirs + + + + + + com.visualgdb.xtensa-esp32-elf + + 12.2.0 + 12.1 + 1 + + + .. + DEBUG + build/$(PlatformName)/$(ConfigurationName) + + false + $(ToolchainNinja) + $(BuildDir) + + + + false + $(SYSPROGS_CMAKE_PATH) + + + true + false + false + Ninja + false + RemoveBuildDirectory + false + + + true + true + true + false + true + false + true + HideOuterProjectTargets + true + false + true + + + true + eadcc9ab-72b3-4b51-a838-593e5d80ddf7 + + Upper + HeaderDirectoryAndSubdirectories + true + + + release/v5.1 + esp-idf/v5.1 + ESPIDF + + COM9 + false + false + ESP32 + + + + + + + + + + + + + + + Default + + + + COM9 + + 115200 + 8 + None + One + None + + + 0 + false + false + false + ASCII + + + 255 + 0 + 0 + 0 + + + 255 + 169 + 169 + 169 + + + 255 + 211 + 211 + 211 + + + 255 + 144 + 238 + 144 + + + 255 + 169 + 169 + 169 + + + + 16 + true + true + true + true + 0 + + LF + false + false + false + + + + true + + + + + Unknown + + true + true + true + + + + false + + + + + Debug + + + + Release + + + + + + + + + false + false + false + false + false + false + false + false + false + + false + false + false + false + false + false + true + false + None + false + false + app_main + true + false + false + true + 0 + false + 0 + true + false + + + openocd + + -f interface/ftdi/tigard.cfg -c "adapter_khz 15000" -f target/esp32.cfg + + + + false + + 131072 + Enabled + + set remotetimeout 60 + target remote :$$SYS:GDB_PORT$$ + mon gdb_breakpoint_override hard + mon reset halt + load + + false + 0 + 0 + false + + 5000 + 1 + true + + size2MB + freq40M + DIO + + true + + + true + Disabled + 0 + false + false + true + false + false + + _estack + 0 + false + + true + + \ No newline at end of file diff --git a/ide/Espressif/ESP-IDF/examples/wolfssh_template/components/wolfssh/CMakeLists.txt b/ide/Espressif/ESP-IDF/examples/wolfssh_template/components/wolfssh/CMakeLists.txt new file mode 100644 index 000000000..6d54b9e74 --- /dev/null +++ b/ide/Espressif/ESP-IDF/examples/wolfssh_template/components/wolfssh/CMakeLists.txt @@ -0,0 +1,508 @@ +# Espressif component/wolfssh/CMakeLists.txt +# +# Copyright (C) 2006-2023 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 2 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 this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA +# +# cmake for WOLFSSH Espressif projects +# +# See https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/build-system.html +# + +cmake_minimum_required(VERSION 3.16) +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DWOLFSSH_USER_SETTINGS") +set(CMAKE_CURRENT_SOURCE_DIR ".") + +# Attention! +# +# When editing component CMake files, consider the following : +# +# NO Managed Componenets: Normal stand-alone app, "as cloned" from github. +# There's no notion of staging names (e.g. mywolfmqtt) regardless of environment settings. +# All of the component source is locall. See settings such s WOLFSSL_ROOT=[your path] +# +# Partially Managed Components. This one is tricky. When publishing a component with examples, +# those examples will have a chicken-and-egg problem: the required component is not yet published. +# Adding to the complexity is the notion of staging components, that are purposely prefixed with +# "my" (e.g. mywolfmqtt) to distinguish from production, live components (e.g. wolfmqtt) +# +# Partially Managed Component Examples are typically only encountered by the component publisher +# and only at publish time, such as when performing the pre-publish build check. +# +# A partially managed component may also be manually created, when adding a managed component to +# and existing project. For example: +# +# idf.py add-dependency "wolfssl/wolfssh^1.4.15-stable" +# +# Fully Managaged Componenets. This is the typical example as created from the Component Registry: +# For example: +# +# idf.py create-project-from-example "wolfssl/wolfssh^1.4.15-stable:wolfssh_server" +# +# In all cases, keep in mind that components other than wolfssl will depend on the wolfssl component. +# + +# Component naming is only adjusted when using Managed Components, and only when using staging site. +if( "$ENV{IDF_COMPONENT_REGISTRY_URL}" STREQUAL "https://components-staging.espressif.com" ) + # TODO: Is checking these two variables really the best way to detect an active Component Manager? + message(STATUS "component_manager_interface_version = ${component_manager_interface_version}") + message(STATUS "managed_components = ${managed_components}") + if( ("${managed_components}" STREQUAL "") AND ("${component_manager_interface_version}" STREQUAL "") ) + # We've found a staging component, but did not detect the component manager + set(WOLFSSL_COMPONENT_NAME "wolfssl") + else() + set(WOLFSSL_COMPONENT_NAME "mywolfssl") + endif() +else() + set(WOLFSSL_COMPONENT_NAME "wolfssl") +endif() + +set(COMPONENT_REQUIRES lwip "${WOLFSSL_COMPONENT_NAME}") + +# COMPONENT_NAME = wolfssh +# The component name is the directory name. "No feature to change this". +# See https://github.com/espressif/esp-idf/issues/8978#issuecomment-1129892685 + +# set the root of WOLFSSH in top-level project CMakelists.txt: +# set(WOLFSSH_ROOT "C:/some path/with/spaces") +# set(WOLFSSH_ROOT "c:/workspace/WOLFSSH-[username]") +# set(WOLFSSH_ROOT "/mnt/c/some path/with/spaces") +# or use this logic to assign value from Environment Variable WOLFSSH_ROOT, +# or assume this is an example 7 subdirectories below: + +# We are typically in [root]/IDE/Espressif/ESP-IDF/examples/WOLFSSH_test/components/WOLFSSH +# The root of WOLFSSH is 7 directories up from here: + +if(CMAKE_BUILD_EARLY_EXPANSION) + message(STATUS "WOLFSSH component CMAKE_BUILD_EARLY_EXPANSION:") + idf_component_register( + REQUIRES "${COMPONENT_REQUIRES}" + PRIV_REQUIRES + esp_timer + driver + "${WOLFSSL_COMPONENT_NAME}" # either wolfssl or mywolfssl as a staging component + ) + +else() + # not CMAKE_BUILD_EARLY_EXPANSION + message(STATUS "************************************************************************************************") + message(STATUS "wolfssh component config:") + message(STATUS "************************************************************************************************") + + # Check to see if we're already in WOLFSSH, and only if WOLFSSH_ROOT not specified + if ("${WOLFSSH_ROOT}" STREQUAL "") + # WOLFSSH examples are 7 directories deep from WOLFSSH repo root + # 1 2 3 4 5 6 7 + set(THIS_RELATIVE_PATH "../../../../../../..") + get_filename_component(THIS_SEARCH_PATH "${THIS_RELATIVE_PATH}" ABSOLUTE) + message(STATUS "Searching in path = ${THIS_SEARCH_PATH}") + + if (EXISTS "${THIS_SEARCH_PATH}/wolfcrypt/src") + # we're already in WOLFSSH examples! + get_filename_component(WOLFSSH_ROOT "${THIS_SEARCH_PATH}" ABSOLUTE) + message(STATUS "Using WOLFSSH example with root ${WOLFSSH_ROOT}") + else() + # We're in some other repo such as wolfssh, so we'll search for an + # adjacent-level directory for WOLFSSH. (8 directories up, then down one) + # + # For example WOLFSSH examples: + # C:\workspace\WOLFSSH-gojimmypi\IDE\Espressif\ESP-IDF\examples\WOLFSSH_benchmark\components\WOLFSSH + # + # For example wolfSSH examples: + # C:\workspace\wolfssh-gojimmypi\ide\Espressif\ESP-IDF\examples\wolfssh_benchmark\components\WOLFSSH + # + # 1 2 3 4 5 6 7 8 + set(THIS_RELATIVE_PATH "../../../../../../../..") + get_filename_component(THIS_SEARCH_PATH "${THIS_RELATIVE_PATH}" ABSOLUTE) + message(STATUS "Searching next in path = ${THIS_SEARCH_PATH}") + endif() + endif() + + # search other possible locations + if ("${WOLFSSH_ROOT}" STREQUAL "") + # there's not a hard-coded WOLFSSH_ROOT value above, so let's see if we can find it. + if( "$ENV{WOLFSSH_ROOT}" STREQUAL "" ) + message(STATUS "Environment Variable WOLFSSH_ROOT not set. Will search common locations.") + + message(STATUS "CMAKE_CURRENT_SOURCE_DIR = ${CMAKE_CURRENT_SOURCE_DIR}") + get_filename_component(THIS_DIR "${CMAKE_CURRENT_SOURCE_DIR}" ABSOLUTE) + message(STATUS "THIS_DIR = ${THIS_DIR}") + + # find the user name to search for possible "WOLFSSH-username" + message(STATUS "USERNAME = $ENV{USERNAME}") + if( "$ENV{USER}" STREQUAL "" ) # the bash user + if( "$ENV{USERNAME}" STREQUAL "" ) # the Windows user + message(STATUS "could not find USER or USERNAME") + else() + # the bash user is not blank, so we'll use it. + set(THIS_USER "$ENV{USERNAME}") + endif() + else() + # the bash user is not blank, so we'll use it. + set(THIS_USER "$ENV{USER}") + endif() + message(STATUS "THIS_USER = ${THIS_USER}") + + # This same makefile is used for both the WOLFSSH component, and other + # components that may depend on WOLFSSH, such as wolfssh. Therefore + # we need to determine if this makefile is in the WOLFSSH repo, or + # some other repo. + + if( "{THIS_USER}" STREQUAL "" ) + # This is highly unusual to not find a user name. + # In this case, we'll just search for a "WOLFSSH" directory: + message(STATUS "No username found!") + get_filename_component(WOLFSSH_ROOT "${THIS_RELATIVE_PATH}/WOLFSSH" ABSOLUTE) + else() + # We found an environment USER name! + # The first place to look for WOLFSSH will be in a user-clone called "WOLFSSH-[username]" + message(STATUS "Using [THIS_USER = ${THIS_USER}] to see if there's a [relative path]/WOLFSSH-${THIS_USER} directory.") + get_filename_component(WOLFSSH_ROOT "${THIS_RELATIVE_PATH}/WOLFSSH-${THIS_USER}" ABSOLUTE) + + if( EXISTS "${WOLFSSH_ROOT}" ) + message(STATUS "Found WOLFSSH in user-suffix ${WOLFSSH_ROOT}") + else() + # If there's not a user-clone called "WOLFSSH-[username]", + # perhaps there's simply a git clone called "WOLFSSH"? + message(STATUS "Did not find WOLFSSH-${THIS_USER}; continuing search...") + get_filename_component(WOLFSSH_ROOT "${THIS_RELATIVE_PATH}/WOLFSSH" ABSOLUTE) + + if( EXISTS "${WOLFSSH_ROOT}" ) + message(STATUS "Found WOLFSSH in standard ${WOLFSSH_ROOT}") + else() + # Things are looking pretty bleak. We'll likely not be able to compile. + message(STATUS "Did not find WOLFSSH in ${WOLFSSH_ROOT}") + endif() + endif() + endif() + + else() + # there's an environment variable, so use it. + set(WOLFSSH_ROOT "$ENV{WOLFSSH_ROOT}") + + if( EXISTS "${WOLFSSH_ROOT}" ) + get_filename_component(WOLFSSH_ROOT "$ENV{WOLFSSH_ROOT}" ABSOLUTE) + message(STATUS "Found WOLFSSH_ROOT via Environment Variable:") + else() + message(FATAL_ERROR "WOLFSSH_ROOT Environment Variable defined, but path not found:") + message(STATUS "$ENV{WOLFSSH_ROOT}") + endif() + endif() + # end of search for WOLFSSH component root + else() + # There's already a value assigned; we won't search for anything else. + message(STATUS "Found user-specified WOLFSSH_ROOT value.") + endif() # WOLFSSH_ROOT user defined + + # After all the logic above, does our WOLFSSH_ROOT actually exist? + if( EXISTS "${WOLFSSH_ROOT}" ) + message(STATUS "WOLFSSH_ROOT = ${WOLFSSH_ROOT}") + else() + # Abort. We need WOLFSSH _somewhere_. + message(FATAL_ERROR "Could not find WOLFSSH in ${WOLFSSH_ROOT}. Try setting environment variable or git clone.") + endif() + + + set(INCLUDE_PATH ${WOLFSSH_ROOT}) + + set(COMPONENT_SRCDIRS + "\"${WOLFSSH_ROOT}/src/\"" + ) # COMPONENT_SRCDIRS + message(STATUS "This COMPONENT_SRCDIRS = ${COMPONENT_SRCDIRS}") + + set(WOLFSSH_PROJECT_DIR "${CMAKE_HOME_DIRECTORY}/components/wolfssh") + + # Espressif may take several passes through this makefile. Check to see if we found IDF + string(COMPARE EQUAL "${PROJECT_SOURCE_DIR}" "" WOLFSSH_FOUND_IDF) + + message(STATUS "IDF_PATH = $ENV{IDF_PATH}") + message(STATUS "PROJECT_SOURCE_DIR = ${PROJECT_SOURCE_DIR}") + message(STATUS "EXCLUDE_ASM = ${EXCLUDE_ASM}") + + # + # Check to see if there's both a local copy and EDP-IDF copy of the WOLFSSH and/or wolfssh components. + # + if( EXISTS "${WOLFSSH_PROJECT_DIR}" AND EXISTS "$ENV{IDF_PATH}/components/WOLFSSH/" ) + # + # WOLFSSH found in both ESP-IDF and local project - needs to be resolved by user + # + message(STATUS "") + message(STATUS "**************************************************************************************") + message(STATUS "") + message(STATUS "Error: Found components/WOLFSSH in both local project and IDF_PATH") + message(STATUS "") + message(STATUS "To proceed: ") + message(STATUS "") + message(STATUS "Remove either the local project component: ${WOLFSSH_PROJECT_DIR} ") + message(STATUS "or the Espressif shared component installed at: $ENV{IDF_PATH}/components/WOLFSSH/ ") + message(STATUS "") + message(FATAL_ERROR "Please use WOLFSSH in either local project or Espressif components, but not both.") + message(STATUS "") + message(STATUS "**************************************************************************************") + message(STATUS "") + + # Optional: if you change the above FATAL_ERROR to STATUS you can warn at runtime with this macro definition: + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DWOLFSSH_MULTI_INSTALL_WARNING") + + else() + if( EXISTS "$ENV{IDF_PATH}/components/WOLFSSH/" ) + # + # WOLFSSH found in ESP-IDF components and is assumed to be already configured in user_settings.h via setup. + # + message(STATUS "") + message(STATUS "Using components/WOLFSSH in IDF_PATH = $ENV{IDF_PATH}") + message(STATUS "") + else() + # + # WOLFSSH is not an ESP-IDF component. + # We need to now determine if it is local and if so if it is part of the WOLFSSH repo, + # or if WOLFSSH is simply installed as a local component. + # + + if( EXISTS "${WOLFSSH_PROJECT_DIR}" ) + # + # WOLFSSH found in local project. + # + if( EXISTS "${WOLFSSH_PROJECT_DIR}/wolfcrypt/" ) + message(STATUS "") + message(STATUS "Using installed project ./components/WOLFSSH in CMAKE_HOME_DIRECTORY = ${CMAKE_HOME_DIRECTORY}") + message(STATUS "") + # + # Note we already checked above and confirmed there's not another WOLFSSH installed in the ESP-IDF components. + # + # We won't do anything else here, as it will be assumed the original install completed successfully. + # + else() # full WOLFSSH not installed in local project + # + # This is the developer repo mode. WOLFSSH will be assumed to be not installed to ESP-IDF nor local project + # In this configuration, we are likely running a WOLFSSH example found directly in the repo. + # + message(STATUS "") + message(STATUS "Using developer repo ./components/WOLFSSH in CMAKE_HOME_DIRECTORY = ${CMAKE_HOME_DIRECTORY}") + message(STATUS "") + + message(STATUS "************************************************************************************************") + # When in developer mode, we are typically running WOLFSSH examples such as benchmark or test directories. + # However, the as-cloned or distributed WOLFSSH does not have the ./include/ directory, so we'll add it as needed. + # + # first check if there's a [root]/include/user_settings.h + if( EXISTS "${WOLFSSH_ROOT}/include/user_settings.h" ) + message(FATAL_ERROR "Found stray WOLFSSH user_settings.h in " + "${WOLFSSH_ROOT}/include/user_settings.h " + " (please move it to ${WOLFSSH_PROJECT_DIR}/include/user_settings.h )") + else() + # we won't overwrite an existing user settings file, just note that we already have one: + if( EXISTS "${WOLFSSH_PROJECT_DIR}/include/user_settings.h" ) + message(STATUS "Using existing WOLFSSH user_settings.h in " + "${WOLFSSH_PROJECT_DIR}/include/user_settings.h") + else() + message(STATUS "Installing WOLFSSH user_settings.h to " + "${WOLFSSH_PROJECT_DIR}/include/user_settings.h") + # file(COPY "${WOLFSSH_ROOT}/IDE/Espressif/ESP-IDF/user_settings.h" + # DESTINATION "${CMAKE_HOME_DIRECTORY}/WOLFSSH/include/") + endif() + endif() # user_settings.h + + message(STATUS "************************************************************************************************") + message(STATUS "") + endif() + + else() + # we did not find a ./components/WOLFSSH/include/ directory from this pass of cmake. + if($WOLFSSH_FOUND_IDF) + message(STATUS "") + message(STATUS "WARNING: WOLFSSH not found.") + message(STATUS "") + else() + # probably needs to be re-parsed by Espressif + message(STATUS "WOLFSSH found IDF. Project Source:${PROJECT_SOURCE_DIR}") + endif() # else we have not found ESP-IDF yet + endif() # else not a local WOLFSSH component + + endif() #else not an ESP-IDF component + endif() # else not local copy and EDP-IDF WOLFSSH + + + # 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/FreeRTOS-Kernel/include/freertos") + + string(REPLACE "\\" "/" WOLFSSH_ROOT ${WOLFSSH_ROOT}) + + if(IS_DIRECTORY "${RTOS_IDF_PATH}") + message(STATUS "Found current RTOS path: ${RTOS_IDF_PATH}") + else() + # ESP-IDF prior version 4.4x has a different RTOS directory structure + string(REPLACE "\\" "/" RTOS_IDF_PATH "$ENV{IDF_PATH}/components/freertos/include/freertos") + if(IS_DIRECTORY "${RTOS_IDF_PATH}") + message(STATUS "Found legacy RTOS path: ${RTOS_IDF_PATH}") + else() + message(STATUS "Could not find RTOS path") + endif() + endif() + + + set(COMPONENT_ADD_INCLUDEDIRS + # "./include" # not used! See wolfSSL include/user_settings.h + "\"${WOLFSSH_ROOT}/\"" + "\"${WOLFSSH_ROOT}/wolfssh/\"" + "\"${RTOS_IDF_PATH}/\"" + ) + + + if(IS_DIRECTORY ${IDF_PATH}/components/cryptoauthlib) + list(APPEND COMPONENT_ADD_INCLUDEDIRS "../cryptoauthlib/lib") + endif() + + list(APPEND COMPONENT_ADD_INCLUDEDIRS "\"${WOLFSSH_ROOT}/wolfssh/\"") + + + + set(COMPONENT_SRCEXCLUDE + # wolfSSH + # TODO: we likely need to check #if !defined(WOLFSSH_MISC_INCLUDED) && !defined(NO_INLINE) && !defined(WOLFSSH_IGNORE_FILE_WARN) + # here in cmake if we actually want to always exclude wolfssh misc.c file. (see source; ok for demo) + "\"${WOLFSSH_ROOT}/src/misc.c\"" # misc.c does not need to be compiled when using inline (NO_INLINE not defined)) + ) + + spaces2list(COMPONENT_REQUIRES) + + separate_arguments(COMPONENT_SRCDIRS NATIVE_COMMAND "${COMPONENT_SRCDIRS}") + separate_arguments(COMPONENT_SRCEXCLUDE NATIVE_COMMAND "${COMPONENT_SRCEXCLUDE}") + separate_arguments(COMPONENT_ADD_INCLUDEDIRS NATIVE_COMMAND "${COMPONENT_ADD_INCLUDEDIRS}") + + # + # See https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/build-system.html#example-component-requirements + # + message(STATUS "COMPONENT_SRCDIRS = ${COMPONENT_SRCDIRS}") + message(STATUS "COMPONENT_ADD_INCLUDEDIRS = ${COMPONENT_ADD_INCLUDEDIRS}") + message(STATUS "COMPONENT_REQUIRES = ${COMPONENT_REQUIRES}") + message(STATUS "COMPONENT_SRCEXCLUDE = ${COMPONENT_SRCEXCLUDE}") + + # + # see https://docs.espressif.com/projects/esp-idf/en/stable/esp32/migration-guides/release-5.x/build-system.html?highlight=space%20path + # + set(EXTRA_COMPONENT_DIRS "${COMPONENT_SRCDIRS}") + idf_component_register( + SRC_DIRS "${COMPONENT_SRCDIRS}" + INCLUDE_DIRS "${COMPONENT_ADD_INCLUDEDIRS}" + REQUIRES "${COMPONENT_REQUIRES}" + EXCLUDE_SRCS "${COMPONENT_SRCEXCLUDE}" + PRIV_REQUIRES + esp_timer + driver + "${WOLFSSL_COMPONENT_NAME}" # either wolfssl or mywolfssl as a staging component + ) + # some optional diagnostics + if (1) + get_cmake_property(_variableNames VARIABLES) + list (SORT _variableNames) + message(STATUS "") + message(STATUS "ALL VARIABLES BEGIN") + message(STATUS "") + foreach (_variableName ${_variableNames}) + message(STATUS "${_variableName}=${${_variableName}}") + endforeach() + message(STATUS "") + message(STATUS "ALL VARIABLES END") + message(STATUS "") + endif() + + # target_sources(WOLFSSH PRIVATE "\"${WOLFSSH_ROOT}/WOLFSSH/\"" "\"${WOLFSSH_ROOT}/WOLFSSH/wolfcrypt\"") +endif() # CMAKE_BUILD_EARLY_EXPANSION + + + +# check to see if there's both a local copy and EDP-IDF copy of the WOLFSSH components +if( EXISTS "${WOLFSSH_PROJECT_DIR}" AND EXISTS "$ENV{IDF_PATH}/components/WOLFSSH/" ) + message(STATUS "") + message(STATUS "") + message(STATUS "********************************************************************") + message(STATUS "WARNING: Found components/WOLFSSH in both local project and IDF_PATH") + message(STATUS "********************************************************************") + message(STATUS "") +endif() +# end multiple component check + + +# +# LIBWOLFSSH_SAVE_INFO(VAR_OUPUT THIS_VAR VAR_RESULT) +# +# Save the THIS_VAR as a string in a macro called VAR_OUPUT +# +# VAR_OUPUT: the name of the macro to define +# THIS_VAR: the OUTPUT_VARIABLE result from a execute_process() +# VAR_RESULT: the RESULT_VARIABLE from a execute_process(); "0" if successful. +# +function ( LIBWOLFSSH_SAVE_INFO VAR_OUPUT THIS_VAR VAR_RESULT ) + # is the RESULT_VARIABLE output value 0? If so, IS_VALID_VALUE is true. + string(COMPARE EQUAL "${VAR_RESULT}" "0" IS_VALID_VALUE) + + # if we had a successful operation, save the THIS_VAR in VAR_OUPUT + if(${IS_VALID_VALUE}) + # strip newline chars in THIS_VAR parameter and save in VAR_VALUE + string(REPLACE "\n" "" VAR_VALUE ${THIS_VAR}) + + # we'll could percolate the value to the parent for possible later use + # set(${VAR_OUPUT} ${VAR_VALUE} PARENT_SCOPE) + + # but we're only using it here in this function + set(${VAR_OUPUT} ${VAR_VALUE}) + + # we'll print what we found to the console + message(STATUS "Found ${VAR_OUPUT}=${VAR_VALUE}") + + # the interesting part is defining the VAR_OUPUT name a value to use in the app + add_definitions(-D${VAR_OUPUT}=\"${VAR_VALUE}\") + else() + # if we get here, check the execute_process command and parameters. + message(STATUS "LIBWOLFSSH_SAVE_INFO encountered a non-zero VAR_RESULT") + set(${VAR_OUPUT} "Unknown") + endif() +endfunction() # LIBWOLFSSH_SAVE_INFO + +# create some programmatic #define values that will be used by ShowExtendedSystemInfo(). +# see wolfcrypt\src\port\Espressif\esp32_utl.c +if(NOT CMAKE_BUILD_EARLY_EXPANSION) + set (git_cmd "git") + message(STATUS "Adding macro definitions:") + + # LIBWOLFSSH_VERSION_GIT_ORIGIN: git config --get remote.origin.url + execute_process(WORKING_DIRECTORY ${WOLFSSH_ROOT} COMMAND ${git_cmd} "config" "--get" "remote.origin.url" OUTPUT_VARIABLE TMP_OUT RESULT_VARIABLE TMP_RES ERROR_QUIET ) + LIBWOLFSSH_SAVE_INFO(LIBWOLFSSH_VERSION_GIT_ORIGIN "${TMP_OUT}" "${TMP_RES}") + + # LIBWOLFSSH_VERSION_GIT_BRANCH: git rev-parse --abbrev-ref HEAD + execute_process(WORKING_DIRECTORY ${WOLFSSH_ROOT} COMMAND ${git_cmd} "rev-parse" "--abbrev-ref" "HEAD" OUTPUT_VARIABLE TMP_OUT RESULT_VARIABLE TMP_RES ERROR_QUIET ) + LIBWOLFSSH_SAVE_INFO(LIBWOLFSSH_VERSION_GIT_BRANCH "${TMP_OUT}" "${TMP_RES}") + + # LIBWOLFSSH_VERSION_GIT_HASH: git rev-parse HEAD + execute_process(WORKING_DIRECTORY ${WOLFSSH_ROOT} COMMAND ${git_cmd} "rev-parse" "HEAD" OUTPUT_VARIABLE TMP_OUT RESULT_VARIABLE TMP_RES ERROR_QUIET ) + LIBWOLFSSH_SAVE_INFO(LIBWOLFSSH_VERSION_GIT_HASH "${TMP_OUT}" "${TMP_RES}") + + # LIBWOLFSSH_VERSION_GIT_SHORT_HASH: git rev-parse --short HEAD + execute_process(WORKING_DIRECTORY ${WOLFSSH_ROOT} COMMAND ${git_cmd} "rev-parse" "--short" "HEAD" OUTPUT_VARIABLE TMP_OUT RESULT_VARIABLE TMP_RES ERROR_QUIET ) + LIBWOLFSSH_SAVE_INFO(LIBWOLFSSH_VERSION_GIT_SHORT_HASH "${TMP_OUT}" "${TMP_RES}") + + # LIBWOLFSSH_VERSION_GIT_HASH_DATE git show --no-patch --no-notes --pretty=\'\%cd\' + execute_process(WORKING_DIRECTORY ${WOLFSSH_ROOT} COMMAND ${git_cmd} "show" "--no-patch" "--no-notes" "--pretty=\'\%cd\'" OUTPUT_VARIABLE TMP_OUT RESULT_VARIABLE TMP_RES ) + LIBWOLFSSH_SAVE_INFO(LIBWOLFSSH_VERSION_GIT_HASH_DATE "${TMP_OUT}" "${TMP_RES}") + + message(STATUS "************************************************************************************************") + message(STATUS "WOLFSSH component config complete!") + message(STATUS "************************************************************************************************") +endif() diff --git a/ide/Espressif/ESP-IDF/examples/wolfssh_template/components/wolfssl/CMakeLists.txt b/ide/Espressif/ESP-IDF/examples/wolfssh_template/components/wolfssl/CMakeLists.txt new file mode 100644 index 000000000..d58704b84 --- /dev/null +++ b/ide/Espressif/ESP-IDF/examples/wolfssh_template/components/wolfssl/CMakeLists.txt @@ -0,0 +1,676 @@ +# +# Copyright (C) 2006-2023 wolfSSL Inc. +# +# This file is part of wolfSSL. +# +# wolfSSL 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 2 of the License, or +# (at your option) any later version. +# +# wolfSSL 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 this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA +# +# cmake for wolfssl Espressif projects +# +# Version 5.6.4.016 for improved manual setting of WOLFSSL_ROOT + ESP8266 support; optional esp-timer / driver components +# +# See https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/build-system.html +# + +cmake_minimum_required(VERSION 3.16) + +set(VERBOSE_COMPONENT_MESSAGES 1) + +# The scope of this CMAKE_C_FLAGS is just this component: +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DWOLFSSL_USER_SETTINGS") + +set(CMAKE_CURRENT_SOURCE_DIR ".") +# set(COMPONENT_REQUIRES lwip) # we typically don't need lwip directly in wolfssl component + +# Optionally set your source to wolfSSL in your project CMakeLists.txt like this: +# set(WOLFSSL_ROOT "c:/test/blogtest/wolfssl" ) + +if ( "${WOLFSSL_ROOT}" STREQUAL "") + set(WOLFSSL_ROOT "$ENV{WOLFSSL_ROOT}" ) +endif() +# Optional compiler definitions to help with system name detection (typically printed by app diagnostics) +if(VERBOSE_COMPONENT_MESSAGES) + if(WIN32) + # Windows-specific configuration here + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DWOLFSSL_CMAKE_SYSTEM_NAME_WINDOWS") + message("Detected Windows") + endif() + if(CMAKE_HOST_UNIX) + message("Detected UNIX") + endif() + if(APPLE) + message("Detected APPLE") + endif() + if(CMAKE_HOST_UNIX AND (NOT APPLE) AND EXISTS "/proc/sys/fs/binfmt_misc/WSLInterop") + # Windows-specific configuration here + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DWOLFSSL_CMAKE_SYSTEM_NAME_WSL") + message("Detected WSL") + endif() + if(CMAKE_HOST_UNIX AND (NOT APPLE) AND (NOT WIN32)) + # Windows-specific configuration here + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DWOLFSSL_CMAKE_SYSTEM_NAME_LINUX") + message("Detected Linux") + endif() + if(APPLE) + # Windows-specific configuration here + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DWOLFSSL_CMAKE_SYSTEM_NAME_APPLE") + message("Detected Apple") + endif() +endif() # End optional WOLFSSL_CMAKE_SYSTEM_NAME + +message(STATUS "CONFIG_TARGET_PLATFORM = ${CONFIG_TARGET_PLATFORM}") + +# Check that there are not conflicting wolfSSL components +# The ESP Registry Component will be in ./managed_components/wolfssl__wolfssl +# The local component wolfSSL directory will be in ./components/wolfssl +if( EXISTS "${CMAKE_HOME_DIRECTORY}/managed_components/wolfssl__wolfssl" AND EXISTS "${CMAKE_HOME_DIRECTORY}/components/wolfssl" ) + # These exclude statements don't seem to be honored by the $ENV{IDF_PATH}/tools/cmake/project.cmake' + # add_subdirectory("${CMAKE_HOME_DIRECTORY}/managed_components/wolfssl__wolfssl" EXCLUDE_FROM_ALL) + # add_subdirectory("${CMAKE_HOME_DIRECTORY}/managed_components/wolfssl__wolfssl/include" EXCLUDE_FROM_ALL) + # So we'll error out and let the user decide how to proceed: + message(WARNING "\nFound wolfSSL components in\n" + "./managed_components/wolfssl__wolfssl\n" + "and\n" + "./components/wolfssl\n" + "in project directory: \n" + "${CMAKE_HOME_DIRECTORY}") + message(FATAL_ERROR "\nPlease use either the ESP Registry Managed Component or the wolfSSL component directory but not both.\n" + "If removing the ./managed_components/wolfssl__wolfssl directory, remember to also remove " + "or rename the idf_component.yml file typically found in ./main/") +else() + message(STATUS "No conflicting wolfSSL components found.") +endif() + + +# Don't include lwip requirement for benchmark and test apps. +if( ("${CMAKE_PROJECT_NAME}" STREQUAL "wolfssl_benchmark") OR ("${CMAKE_PROJECT_NAME}" STREQUAL "wolfssl_test") ) + message(STATUS "Not including lwip for ${CMAKE_PROJECT_NAME}") +else() + # benchmark and test do not need wifi, everything else probably does: + set(COMPONENT_REQUIRES lwip) # we typically don't need lwip directly in wolfssl component +endif() + +# find the user name to search for possible "wolfssl-username" +message(STATUS "USERNAME = $ENV{USERNAME}") +if( "$ENV{USER}" STREQUAL "" ) # the bash user + if( "$ENV{USERNAME}" STREQUAL "" ) # the Windows user + message(STATUS "could not find USER or USERNAME") + else() + # the bash user is not blank, so we'll use it. + set(THIS_USER "$ENV{USERNAME}") + endif() +else() + # the bash user is not blank, so we'll use it. + set(THIS_USER "$ENV{USER}") +endif() +message(STATUS "THIS_USER = ${THIS_USER}") + + +# COMPONENT_NAME = wolfssl +# The component name is the directory name. "No feature to change this". +# See https://github.com/espressif/esp-idf/issues/8978#issuecomment-1129892685 + +# set the root of wolfSSL in top-level project CMakelists.txt: +# set(WOLFSSL_ROOT "C:/some path/with/spaces") +# set(WOLFSSL_ROOT "c:/workspace/wolfssl-[username]") +# set(WOLFSSL_ROOT "/mnt/c/some path/with/spaces") +# or use this logic to assign value from Environment Variable WOLFSSL_ROOT, +# or assume this is an example 7 subdirectories below: + +# We are typically in [root]/IDE/Espressif/ESP-IDF/examples/wolfssl_test/components/wolfssl +# The root of wolfSSL is 7 directories up from here: + +# function: IS_WOLFSSL_SOURCE +# parameter: DIRECTORY_PARAMETER - the directory to test +# output: RESULT = contains contents of DIRECTORY_PARAMETER for wolfssl directory, otherwise blank. +function(IS_WOLFSSL_SOURCE DIRECTORY_PARAMETER RESULT) + if (EXISTS "${DIRECTORY_PARAMETER}/wolfcrypt/src") + set(${RESULT} "${DIRECTORY_PARAMETER}" PARENT_SCOPE) + else() + set(${RESULT} "" PARENT_SCOPE) + endif() +endfunction() + +# ********************************************************************************************* +# function: FIND_WOLFSSL_DIRECTORY +# parameter: OUTPUT_FOUND_WOLFSSL_DIRECTORY contains root of source code, otherwise blank +# +# Example usage: +# FIND_WOLFSSL_DIRECTORY(WOLFSSL_ROOT) +# ********************************************************************************************* +function(FIND_WOLFSSL_DIRECTORY OUTPUT_FOUND_WOLFSSL_DIRECTORY) + message(STATUS "Starting FIND_WOLFSSL_DIRECTORY: ${${OUTPUT_FOUND_WOLFSSL_DIRECTORY}}") + + if ( "${${OUTPUT_FOUND_WOLFSSL_DIRECTORY}}" STREQUAL "" ) + set(CURRENT_SEARCH_DIR "$ENV{WOLFSSL_ROOT}") + if( "${CURRENT_SEARCH_DIR}" STREQUAL "" ) + message(STATUS "The WOLFSSL_ROOT environment variable is not set. Searching...") + else() + get_filename_component(CURRENT_SEARCH_DIR "$ENV{WOLFSSL_ROOT}" ABSOLUTE) + IS_WOLFSSL_SOURCE("${CURRENT_SEARCH_DIR}" FOUND_WOLFSSL) + if( FOUND_WOLFSSL ) + message(STATUS "Found WOLFSSL_ROOT via Environment Variable:") + else() + message(FATAL_ERROR "WOLFSSL_ROOT Environment Variable defined, but path not found:") + message(STATUS "$ENV{WOLFSSL_ROOT}") + endif() + endif() + else() + get_filename_component(CURRENT_SEARCH_DIR "${${OUTPUT_FOUND_WOLFSSL_DIRECTORY}}" ABSOLUTE) + IS_WOLFSSL_SOURCE("${CURRENT_SEARCH_DIR}" FOUND_WOLFSSL) + if( FOUND_WOLFSSL ) + message(STATUS "Found WOLFSSL_ROOT via prior specification.") + else() + message(FATAL_ERROR "WOLFSSL_ROOT Variable defined, but path not found: ${${OUTPUT_FOUND_WOLFSSL_DIRECTORY}}") + endif() + endif() + + + # we'll start in the CMAKE_CURRENT_SOURCE_DIR, typically [something]/projectname/components/wolfssl + message(STATUS "CMAKE_CURRENT_SOURCE_DIR = ${CMAKE_CURRENT_SOURCE_DIR}") + get_filename_component(CURRENT_SEARCH_DIR "${CMAKE_CURRENT_SOURCE_DIR}" ABSOLUTE) + message(STATUS "CURRENT_SEARCH_DIR = ${CURRENT_SEARCH_DIR}") + string(LENGTH ${CURRENT_SEARCH_DIR} CURRENT_SEARCH_DIR_LENGTH) + + # loop through all the parents, looking for wolfssl + while(NOT CURRENT_SEARCH_DIR STREQUAL "/" AND NOT CURRENT_SEARCH_DIR STREQUAL "" ) + string(LENGTH ${CURRENT_SEARCH_DIR} CURRENT_SEARCH_DIR_LENGTH) + # wolfSSL may simply be in a parent directory, such as for local examples in wolfssl repo + IS_WOLFSSL_SOURCE("${CURRENT_SEARCH_DIR}" FOUND_WOLFSSL) + if( FOUND_WOLFSSL ) + message(STATUS "Found wolfssl in CURRENT_SEARCH_DIR = ${CURRENT_SEARCH_DIR}") + set(${OUTPUT_FOUND_WOLFSSL_DIRECTORY} ${CURRENT_SEARCH_DIR} PARENT_SCOPE) + return() + endif() + + if( THIS_USER ) + # Check for "wolfssl-[username]" subdirectory as we recurse up the directory tree + set(CURRENT_SEARCH_DIR_ALT ${CURRENT_SEARCH_DIR}/wolfssl-${THIS_USER}) + message(STATUS "Looking in ${CURRENT_SEARCH_DIR}") + + #if(EXISTS ${CURRENT_SEARCH_DIR_ALT} AND IS_DIRECTORY ${CURRENT_SEARCH_DIR_ALT} AND EXISTS "${CURRENT_SEARCH_DIR_ALT}/wolfcrypt/src") + IS_WOLFSSL_SOURCE("${CURRENT_SEARCH_DIR_ALT}" FOUND_WOLFSSL ) + if ( FOUND_WOLFSSL ) + message(STATUS "Found wolfssl in user-suffix CURRENT_SEARCH_DIR_ALT = ${CURRENT_SEARCH_DIR_ALT}") + set(${OUTPUT_FOUND_WOLFSSL_DIRECTORY} ${CURRENT_SEARCH_DIR_ALT} PARENT_SCOPE) + return() + endif() + endif() + + # Next check for no user suffix "wolfssl" subdirectory as we recurse up the directory tree + set(CURRENT_SEARCH_DIR_ALT ${CURRENT_SEARCH_DIR}/wolfssl) + # if(EXISTS ${CURRENT_SEARCH_DIR} AND IS_DIRECTORY ${CURRENT_SEARCH_DIR} AND EXISTS "${CURRENT_SEARCH_DIR}/wolfcrypt/src") + IS_WOLFSSL_SOURCE("${CURRENT_SEARCH_DIR_ALT}" FOUND_WOLFSSL ) + if ( FOUND_WOLFSSL ) + message(STATUS "Found wolfssl in CURRENT_SEARCH_DIR = ${CURRENT_SEARCH_DIR}") + set(${OUTPUT_FOUND_WOLFSSL_DIRECTORY} ${CURRENT_SEARCH_DIR} PARENT_SCOPE) + return() + endif() + + # Move up one directory level + set(PRIOR_SEARCH_DIR "${CURRENT_SEARCH_DIR}") + get_filename_component(CURRENT_SEARCH_DIR "${CURRENT_SEARCH_DIR}" DIRECTORY) + message(STATUS "Next CURRENT_SEARCH_DIR = ${CURRENT_SEARCH_DIR}") + if( "${PRIOR_SEARCH_DIR}" STREQUAL "${CURRENT_SEARCH_DIR}" ) + # when the search directory is empty, we'll give up + set(CURRENT_SEARCH_DIR "") + endif() + endwhile() + + # If not found, set the output variable to empty before exiting + set(${OUTPUT_FOUND_WOLFSSL_DIRECTORY} "" PARENT_SCOPE) +endfunction() + + +# Example usage: +# +# Simply find the WOLFSSL_DIRECTORY by searching parent directories: +# FIND_WOLFSSL_DIRECTORY(WOLFSSL_ROOT) +# + +if(CMAKE_BUILD_EARLY_EXPANSION) + message(STATUS "wolfssl component CMAKE_BUILD_EARLY_EXPANSION:") + idf_component_register( + REQUIRES "${COMPONENT_REQUIRES}" + PRIV_REQUIRES # esp_hw_support + "${THIS_INCLUDE_TIMER}" + "${THIS_INCLUDE_DRIVER}" # this will typically only be needed for wolfSSL benchmark + ) + +else() + # not CMAKE_BUILD_EARLY_EXPANSION + message(STATUS "************************************************************************************************") + message(STATUS "wolfssl component config:") + message(STATUS "************************************************************************************************") + + if ( "${CONFIG_TARGET_PLATFORM}" STREQUAL "esp8266") + # There's no esp_timer, no driver components for the ESP8266 + set(THIS_INCLUDE_TIMER "") + set(THIS_INCLUDE_DRIVER "") + else() + set(THIS_INCLUDE_TIMER "esp_timer") + set(THIS_INCLUDE_DRIVER "driver") + endif() + + # search for wolfSSL + # TODO allow for cmake prior def + + if(WOLFSSL_ROOT) + IS_WOLFSSL_SOURCE("${WOLFSSL_ROOT}" FOUND_WOLFSSL) + if(FOUND_WOLFSSL) + message(STATUS "Found WOLFSSL_ROOT via CMake specification.") + else() + # WOLFSSL_ROOT Path specified in CMakeLists.txt is not a valid path + message(FATAL_ERROR "WOLFSSL_ROOT CMake Variable defined, but path not found: ${WOLFSSL_ROOT}\n" + "Try correcting WOLFSSL_ROOT in your project CMakeFile.txt or setting environment variable.") + # Abort CMake after fatal error. + endif() + else() + message(STATUS "Searching for wolfSL source code...") + FIND_WOLFSSL_DIRECTORY(WOLFSSL_ROOT) + endif() + + + if(WOLFSSL_ROOT) + message(STATUS "Confirmed wolfssl directory at: ${WOLFSSL_ROOT}") + else() + message(STATUS "Failed: wolfssl directory not found.") + # Abort. We need wolfssl _somewhere_. + message(FATAL_ERROR "Could not find wolfssl in ${WOLFSSL_ROOT}.\n" + "Try setting WOLFSSL_ROOT environment variable or git clone.") + # Abort CMake after fatal error. + endif() + + set(INCLUDE_PATH ${WOLFSSL_ROOT}) + + set(WOLFSSL_EXTRA_PROJECT_DIR "${WOLFSSL_ROOT}/src/") + + # During regression tests, optionally copy source locally and use: set(USE_LOCAL_TEST_BENCH 1) + set(USE_LOCAL_TEST_BENCH 0) + if(NOT USE_LOCAL_TEST_BENCH) + if( "${CMAKE_PROJECT_NAME}" STREQUAL "hello-world" ) + message(STATUS "Include ${WOLFSSL_ROOT}/wolfcrypt/benchmark") + set(WOLFSSL_EXTRA_PROJECT_DIR "${WOLFSSL_ROOT}/wolfcrypt/benchmark") + endif() + + if( "${CMAKE_PROJECT_NAME}" STREQUAL "wolfssl_benchmark" ) + message(STATUS "Include ${WOLFSSL_ROOT}/wolfcrypt/benchmark") + set(WOLFSSL_EXTRA_PROJECT_DIR "${WOLFSSL_ROOT}/wolfcrypt/benchmark") + endif() + + if( "${CMAKE_PROJECT_NAME}" STREQUAL "wolfssl_test" ) + message(STATUS "Include ${WOLFSSL_ROOT}/wolfcrypt/test") + set(WOLFSSL_EXTRA_PROJECT_DIR "${WOLFSSL_ROOT}/wolfcrypt/test") + endif() + endif() + + set(COMPONENT_SRCDIRS "\"${WOLFSSL_ROOT}/src/\"" + "\"${WOLFSSL_ROOT}/wolfcrypt/src\"" + "\"${WOLFSSL_ROOT}/wolfcrypt/src/port/Espressif\"" + "\"${WOLFSSL_ROOT}/wolfcrypt/src/port/atmel\"" + "\"${WOLFSSL_EXTRA_PROJECT_DIR}\"" + ) # COMPONENT_SRCDIRS + + message(STATUS "This COMPONENT_SRCDIRS = ${COMPONENT_SRCDIRS}") + + # wolfSSL user_settings.h is in the local project. + set(WOLFSSL_PROJECT_DIR "${CMAKE_HOME_DIRECTORY}/components/wolfssl") + + string(REPLACE "/" "//" STR_WOLFSSL_PROJECT_DIR "${WOLFSSL_PROJECT_DIR}") + add_definitions(-DWOLFSSL_USER_SETTINGS_DIR="${STR_WOLFSSL_PROJECT_DIR}//include//user_settings.h") + + # Espressif may take several passes through this makefile. Check to see if we found IDF + string(COMPARE EQUAL "${PROJECT_SOURCE_DIR}" "" WOLFSSL_FOUND_IDF) + + # get a list of all wolfcrypt assembly files; we'll exclude them as they don't target Xtensa + file(GLOB EXCLUDE_ASM *.S) + file(GLOB EXCLUDE_ASM ${CMAKE_SOURCE_DIR} "${WOLFSSL_ROOT}/wolfcrypt/src/*.S") + + message(STATUS "IDF_PATH = $ENV{IDF_PATH}") + message(STATUS "PROJECT_SOURCE_DIR = ${PROJECT_SOURCE_DIR}") + message(STATUS "EXCLUDE_ASM = ${EXCLUDE_ASM}") + + # + # Check to see if there's both a local copy and EDP-IDF copy of the wolfssl and/or wolfssh components. + # + if( EXISTS "${WOLFSSL_PROJECT_DIR}" AND EXISTS "$ENV{IDF_PATH}/components/wolfssl/" ) + # + # wolfSSL found in both ESP-IDF and local project - needs to be resolved by user + # + message(STATUS "") + message(STATUS "**************************************************************************************") + message(STATUS "") + message(STATUS "Error: Found components/wolfssl in both local project and IDF_PATH") + message(STATUS "") + message(STATUS "To proceed: ") + message(STATUS "") + message(STATUS "Remove either the local project component: ${WOLFSSL_PROJECT_DIR} ") + message(STATUS "or the Espressif shared component installed at: $ENV{IDF_PATH}/components/wolfssl/ ") + message(STATUS "") + message(STATUS "") + message(STATUS "**************************************************************************************") + message(STATUS "") + + message(FATAL_ERROR "Please use wolfSSL in either local project or Espressif components, but not both.") + # Abort CMake after fatal error. + + # Optional: if you change the above FATAL_ERROR to STATUS you can warn at runtime with this macro definition: + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DWOLFSSL_MULTI_INSTALL_WARNING") + + else() + if( EXISTS "$ENV{IDF_PATH}/components/wolfssl/" ) + # + # wolfSSL found in ESP-IDF components and is assumed to be already configured in user_settings.h via setup. + # + message(STATUS "") + message(STATUS "Using components/wolfssl in IDF_PATH = $ENV{IDF_PATH}") + message(STATUS "") + else() + # + # wolfSSL is not an ESP-IDF component. + # We need to now determine if it is local and if so if it is part of the wolfSSL repo, + # or if wolfSSL is simply installed as a local component. + # + + if( EXISTS "${WOLFSSL_PROJECT_DIR}" ) + # + # wolfSSL found in local project. + # + if( EXISTS "${WOLFSSL_PROJECT_DIR}/wolfcrypt/" ) + message(STATUS "") + message(STATUS "Using installed project ./components/wolfssl in CMAKE_HOME_DIRECTORY = ${CMAKE_HOME_DIRECTORY}") + message(STATUS "") + # + # Note we already checked above and confirmed there's not another wolfSSL installed in the ESP-IDF components. + # + # We won't do anything else here, as it will be assumed the original install completed successfully. + # + else() # full wolfSSL not installed in local project + # + # This is the developer repo mode. wolfSSL will be assumed to be not installed to ESP-IDF nor local project + # In this configuration, we are likely running a wolfSSL example found directly in the repo. + # + message(STATUS "") + message(STATUS "Using developer repo ./components/wolfssl in CMAKE_HOME_DIRECTORY = ${CMAKE_HOME_DIRECTORY}") + message(STATUS "") + + message(STATUS "************************************************************************************************") + # When in developer mode, we are typically running wolfSSL examples such as benchmark or test directories. + # However, the as-cloned or distributed wolfSSL does not have the ./include/ directory, so we'll add it as needed. + # + # first check if there's a [root]/include/user_settings.h + if( EXISTS "${WOLFSSL_ROOT}/include/user_settings.h" ) + message(FATAL_ERROR "Found stray wolfSSL user_settings.h in " + "${WOLFSSL_ROOT}/include/user_settings.h " + " (please move it to ${WOLFSSL_PROJECT_DIR}/include/user_settings.h )") + # Abort CMake after fatal error. + else() + # we won't overwrite an existing user settings file, just note that we already have one: + if( EXISTS "${WOLFSSL_PROJECT_DIR}/include/user_settings.h" ) + message(STATUS "Using existing wolfSSL user_settings.h in " + "${WOLFSSL_PROJECT_DIR}/include/user_settings.h") + else() + message(STATUS "Installing wolfSSL user_settings.h to " + "${WOLFSSL_PROJECT_DIR}/include/user_settings.h") + file(COPY "${WOLFSSL_ROOT}/IDE/Espressif/ESP-IDF/user_settings.h" + DESTINATION "${CMAKE_HOME_DIRECTORY}/wolfssl/include/") + endif() + endif() # user_settings.h + + # next check if there's a [root]/include/config.h + if( EXISTS "${WOLFSSL_ROOT}/include/config.h" ) + message(STATUS "******************************************************************************") + message(STATUS "******************************************************************************") + message(STATUS "Found stray wolfSSL config.h in ${WOLFSSL_ROOT}/include/config.h" ) + message(STATUS " Please move it to ${WOLFSSL_PROJECT_DIR}/include/config.h" ) + message(STATUS "******************************************************************************") + message(STATUS "******************************************************************************") + else() + # we won't overwrite an existing user settings file, just note that we already have one: + if( EXISTS "${WOLFSSL_PROJECT_DIR}/include/config.h" ) + message(STATUS "Using existing wolfSSL config.h ${WOLFSSL_PROJECT_DIR}/include/config.h") + else() + message(STATUS "Installing wolfSSL config.h to ${WOLFSSL_PROJECT_DIR}/include/config.h") + file(COPY "${WOLFSSL_ROOT}/IDE/Espressif/ESP-IDF/dummy_config_h" DESTINATION "${WOLFSSL_PROJECT_DIR}/include/") + file(RENAME "${WOLFSSL_PROJECT_DIR}/include/dummy_config_h" "${WOLFSSL_PROJECT_DIR}/include/config.h") + endif() # Project config.h + endif() # WOLFSSL_ROOT config.h + message(STATUS "************************************************************************************************") + message(STATUS "") + endif() + + else() + # we did not find a ./components/wolfssl/include/ directory from this pass of cmake. + if($WOLFSSL_FOUND_IDF) + message(STATUS "") + message(STATUS "WARNING: wolfSSL not found.") + message(STATUS "") + else() + # probably needs to be re-parsed by Espressif + message(STATUS "wolfSSL found IDF. Project Source:${PROJECT_SOURCE_DIR}") + endif() # else we have not found ESP-IDF yet + endif() # else not a local wolfSSL component + + endif() #else not an ESP-IDF component + endif() # else not local copy and EDP-IDF wolfSSL + + + # 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/FreeRTOS-Kernel/include/freertos") + + string(REPLACE "\\" "/" WOLFSSL_ROOT ${WOLFSSL_ROOT}) + + if(IS_DIRECTORY "${RTOS_IDF_PATH}") + message(STATUS "Found current RTOS path: ${RTOS_IDF_PATH}") + else() + # ESP-IDF prior version 4.4x has a different RTOS directory structure + string(REPLACE "\\" "/" RTOS_IDF_PATH "$ENV{IDF_PATH}/components/freertos/include/freertos") + if(IS_DIRECTORY "${RTOS_IDF_PATH}") + message(STATUS "Found legacy RTOS path: ${RTOS_IDF_PATH}") + else() + message(STATUS "Could not find RTOS path") + endif() + endif() + + # wolfSSL-specific include directories + set(COMPONENT_ADD_INCLUDEDIRS + "./include" # this is the location of local project wolfssl user_settings.h + "\"${WOLFSSL_ROOT}/\"" + "\"${WOLFSSL_ROOT}/wolfssl/\"" + "\"${WOLFSSL_ROOT}/wolfssl/wolfcrypt/\"" + "\"${WOLFSSL_ROOT}/wolfssl/wolfcrypt/port/Espressif\"" + "\"${RTOS_IDF_PATH}/\"" + ) + + # Optionally include cryptoauthlib if present + if(IS_DIRECTORY ${IDF_PATH}/components/cryptoauthlib) + list(APPEND COMPONENT_ADD_INCLUDEDIRS "../cryptoauthlib/lib") + endif() + + list(APPEND COMPONENT_ADD_INCLUDEDIRS "\"${WOLFSSL_ROOT}/wolfssl/\"") + list(APPEND COMPONENT_ADD_INCLUDEDIRS "\"${WOLFSSL_ROOT}/wolfssl/wolfcrypt/\"") + + + # Some files are known to be included elsewhere, or not used for Espressif + set(COMPONENT_SRCEXCLUDE + "\"${WOLFSSL_ROOT}/src/bio.c\"" + "\"${WOLFSSL_ROOT}/src/conf.c\"" + "\"${WOLFSSL_ROOT}/src/misc.c\"" + "\"${WOLFSSL_ROOT}/src/pk.c\"" + "\"${WOLFSSL_ROOT}/src/ssl_asn1.c\"" # included by ssl.c + "\"${WOLFSSL_ROOT}/src/ssl_bn.c\"" # included by ssl.c + "\"${WOLFSSL_ROOT}/src/ssl_certman.c\"" # included by ssl.c + "\"${WOLFSSL_ROOT}/src/ssl_crypto.c\"" # included by ssl.c + "\"${WOLFSSL_ROOT}/src/ssl_misc.c\"" # included by ssl.c + "\"${WOLFSSL_ROOT}/src/x509.c\"" + "\"${WOLFSSL_ROOT}/src/x509_str.c\"" + "\"${WOLFSSL_ROOT}/wolfcrypt/src/evp.c\"" + "\"${WOLFSSL_ROOT}/wolfcrypt/src/misc.c\"" + "\"${WOLFSSL_ROOT}/wolfcrypt/src/sp_sm2_arm32.c\"" + "\"${WOLFSSL_ROOT}/wolfcrypt/src/sp_sm2_arm64.c\"" + "\"${WOLFSSL_ROOT}/wolfcrypt/src/sp_sm2_armthumb.c\"" + "\"${WOLFSSL_ROOT}/wolfcrypt/src/sp_sm2_c32.c\"" + "\"${WOLFSSL_ROOT}/wolfcrypt/src/sp_sm2_c64.c\"" + "\"${WOLFSSL_ROOT}/wolfcrypt/src/sp_sm2_cortexm.c\"" + "\"${WOLFSSL_ROOT}/wolfcrypt/src/sp_sm2_x86_64.c\"" + "\"${WOLFSSL_ROOT}/wolfcrypt/src/sp_sm2_x86_64_asm.S\"" + "\"${EXCLUDE_ASM}\"" + ) + + spaces2list(COMPONENT_REQUIRES) + + separate_arguments(COMPONENT_SRCDIRS NATIVE_COMMAND "${COMPONENT_SRCDIRS}") + separate_arguments(COMPONENT_SRCEXCLUDE NATIVE_COMMAND "${COMPONENT_SRCEXCLUDE}") + separate_arguments(COMPONENT_ADD_INCLUDEDIRS NATIVE_COMMAND "${COMPONENT_ADD_INCLUDEDIRS}") + + # + # See https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/build-system.html#example-component-requirements + # + message(STATUS "COMPONENT_SRCDIRS = ${COMPONENT_SRCDIRS}") + message(STATUS "COMPONENT_ADD_INCLUDEDIRS = ${COMPONENT_ADD_INCLUDEDIRS}") + message(STATUS "COMPONENT_REQUIRES = ${COMPONENT_REQUIRES}") + message(STATUS "COMPONENT_SRCEXCLUDE = ${COMPONENT_SRCEXCLUDE}") + + # + # see https://docs.espressif.com/projects/esp-idf/en/stable/esp32/migration-guides/release-5.x/build-system.html?highlight=space%20path + # + set(EXTRA_COMPONENT_DIRS "${COMPONENT_SRCDIRS}") + idf_component_register( + SRC_DIRS "${COMPONENT_SRCDIRS}" + INCLUDE_DIRS "${COMPONENT_ADD_INCLUDEDIRS}" + REQUIRES "${COMPONENT_REQUIRES}" + EXCLUDE_SRCS "${COMPONENT_SRCEXCLUDE}" + PRIV_REQUIRES + "${THIS_INCLUDE_TIMER}" + "${THIS_INCLUDE_DRIVER}" # this will typically only be needed for wolfSSL benchmark + ) + + # Some optional diagnostics. Verbose ones are truncated. + if (VERBOSE_COMPONENT_MESSAGES) + get_cmake_property(_variableNames VARIABLES) + list (SORT _variableNames) + message(STATUS "") + message(STATUS "ALL VARIABLES BEGIN") + message(STATUS "") + foreach (_variableName ${_variableNames}) + if ( ("${_variableName}" STREQUAL "bootloader_binary_files") + OR ("${_variableName}" STREQUAL "Component paths") + OR ("${_variableName}" STREQUAL "component_targets") + OR ("${_variableName}" STREQUAL "__COMPONENT_TARGETS") + OR ("${_variableName}" STREQUAL "CONFIGS_LIST") + OR ("${_variableName}" STREQUAL "__CONFIG_VARIABLES") + OR ("${_variableName}" STREQUAL "val") + OR ("${_variableName}" MATCHES "^__idf_") + ) + # Truncate the displayed value: + string(SUBSTRING "${${_variableName}}" 0 70 truncatedValue) + message(STATUS "${_variableName} = ${truncatedValue} ... (truncated)") + else() + message(STATUS "${_variableName}=${${_variableName}}") + endif() + endforeach() + message(STATUS "") + message(STATUS "ALL VARIABLES END") + message(STATUS "") + endif() + + # target_sources(wolfssl PRIVATE "\"${WOLFSSL_ROOT}/wolfssl/\"" "\"${WOLFSSL_ROOT}/wolfssl/wolfcrypt\"") + +endif() # CMAKE_BUILD_EARLY_EXPANSION + + + +# check to see if there's both a local copy and EDP-IDF copy of the wolfssl components +if( EXISTS "${WOLFSSL_PROJECT_DIR}" AND EXISTS "$ENV{IDF_PATH}/components/wolfssl/" ) + message(STATUS "") + message(STATUS "") + message(STATUS "********************************************************************") + message(STATUS "WARNING: Found components/wolfssl in both local project and IDF_PATH") + message(STATUS "********************************************************************") + message(STATUS "") +endif() +# end multiple component check + + +# +# LIBWOLFSSL_SAVE_INFO(VAR_OUPUT THIS_VAR VAR_RESULT) +# +# Save the THIS_VAR as a string in a macro called VAR_OUPUT +# +# VAR_OUPUT: the name of the macro to define +# THIS_VAR: the OUTPUT_VARIABLE result from a execute_process() +# VAR_RESULT: the RESULT_VARIABLE from a execute_process(); "0" if successful. +# +function ( LIBWOLFSSL_SAVE_INFO VAR_OUPUT THIS_VAR VAR_RESULT ) + # is the RESULT_VARIABLE output value 0? If so, IS_VALID_VALUE is true. + string(COMPARE EQUAL "${VAR_RESULT}" "0" IS_VALID_VALUE) + + # if we had a successful operation, save the THIS_VAR in VAR_OUPUT + if(${IS_VALID_VALUE}) + # strip newline chars in THIS_VAR parameter and save in VAR_VALUE + string(REPLACE "\n" "" VAR_VALUE ${THIS_VAR}) + + # we'll could percolate the value to the parent for possible later use + # set(${VAR_OUPUT} ${VAR_VALUE} PARENT_SCOPE) + + # but we're only using it here in this function + set(${VAR_OUPUT} ${VAR_VALUE}) + + # we'll print what we found to the console + message(STATUS "Found ${VAR_OUPUT}=${VAR_VALUE}") + + # the interesting part is defining the VAR_OUPUT name a value to use in the app + add_definitions(-D${VAR_OUPUT}=\"${VAR_VALUE}\") + else() + # if we get here, check the execute_process command and parameters. + message(STATUS "LIBWOLFSSL_SAVE_INFO encountered a non-zero VAR_RESULT") + set(${VAR_OUPUT} "Unknown") + endif() +endfunction() # LIBWOLFSSL_SAVE_INFO + +# create some programmatic #define values that will be used by ShowExtendedSystemInfo(). +# see wolfcrypt\src\port\Espressif\esp32_utl.c +if(NOT CMAKE_BUILD_EARLY_EXPANSION) + set (git_cmd "git") + message(STATUS "Adding macro definitions:") + + # LIBWOLFSSL_VERSION_GIT_ORIGIN: git config --get remote.origin.url + execute_process(WORKING_DIRECTORY ${WOLFSSL_ROOT} COMMAND ${git_cmd} "config" "--get" "remote.origin.url" OUTPUT_VARIABLE TMP_OUT RESULT_VARIABLE TMP_RES ERROR_QUIET ) + LIBWOLFSSL_SAVE_INFO(LIBWOLFSSL_VERSION_GIT_ORIGIN "${TMP_OUT}" "${TMP_RES}") + + # LIBWOLFSSL_VERSION_GIT_BRANCH: git rev-parse --abbrev-ref HEAD + execute_process(WORKING_DIRECTORY ${WOLFSSL_ROOT} COMMAND ${git_cmd} "rev-parse" "--abbrev-ref" "HEAD" OUTPUT_VARIABLE TMP_OUT RESULT_VARIABLE TMP_RES ERROR_QUIET ) + LIBWOLFSSL_SAVE_INFO(LIBWOLFSSL_VERSION_GIT_BRANCH "${TMP_OUT}" "${TMP_RES}") + + # LIBWOLFSSL_VERSION_GIT_HASH: git rev-parse HEAD + execute_process(WORKING_DIRECTORY ${WOLFSSL_ROOT} COMMAND ${git_cmd} "rev-parse" "HEAD" OUTPUT_VARIABLE TMP_OUT RESULT_VARIABLE TMP_RES ERROR_QUIET ) + LIBWOLFSSL_SAVE_INFO(LIBWOLFSSL_VERSION_GIT_HASH "${TMP_OUT}" "${TMP_RES}") + + # LIBWOLFSSL_VERSION_GIT_SHORT_HASH: git rev-parse --short HEAD + execute_process(WORKING_DIRECTORY ${WOLFSSL_ROOT} COMMAND ${git_cmd} "rev-parse" "--short" "HEAD" OUTPUT_VARIABLE TMP_OUT RESULT_VARIABLE TMP_RES ERROR_QUIET ) + LIBWOLFSSL_SAVE_INFO(LIBWOLFSSL_VERSION_GIT_SHORT_HASH "${TMP_OUT}" "${TMP_RES}") + + # LIBWOLFSSL_VERSION_GIT_HASH_DATE git show --no-patch --no-notes --pretty=\'\%cd\' + execute_process(WORKING_DIRECTORY ${WOLFSSL_ROOT} COMMAND ${git_cmd} "show" "--no-patch" "--no-notes" "--pretty=\'\%cd\'" OUTPUT_VARIABLE TMP_OUT RESULT_VARIABLE TMP_RES ) + LIBWOLFSSL_SAVE_INFO(LIBWOLFSSL_VERSION_GIT_HASH_DATE "${TMP_OUT}" "${TMP_RES}") + + LIBWOLFSSL_SAVE_INFO(LIBWOLFSSL_VERSION_WOLFSSL_ROOT "${WOLFSSL_ROOT}" "${TMP_RES}") + + message(STATUS "************************************************************************************************") + message(STATUS "wolfssl component config complete!") + message(STATUS "************************************************************************************************") +endif() diff --git a/ide/Espressif/ESP-IDF/examples/wolfssh_template/components/wolfssl/README.md b/ide/Espressif/ESP-IDF/examples/wolfssh_template/components/wolfssl/README.md new file mode 100644 index 000000000..040c8c0ba --- /dev/null +++ b/ide/Espressif/ESP-IDF/examples/wolfssh_template/components/wolfssl/README.md @@ -0,0 +1,9 @@ +# Component wolfSSL + +This `wolfssl` directory exists only for the stand-alone examples. + +The only files of interest are the [CMakeLists.txt](./CMakeLists.txt) that should point +to the wolfSSL source code and the respective [include/user_settings.h](./include/user_settings.h). + +This directory is _not_ included in the publish to the Espressif Registry, as that +mechanism copies the published source code to the local component directory as needed. diff --git a/ide/Espressif/ESP-IDF/examples/wolfssh_template/components/wolfssl/include/user_settings.h b/ide/Espressif/ESP-IDF/examples/wolfssh_template/components/wolfssl/include/user_settings.h new file mode 100644 index 000000000..41f588a01 --- /dev/null +++ b/ide/Espressif/ESP-IDF/examples/wolfssh_template/components/wolfssl/include/user_settings.h @@ -0,0 +1,508 @@ +/* user_settings.h + * + * Copyright (C) 2006-2023 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL 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 2 of the License, or + * (at your option) any later version. + * + * wolfSSL 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +#include /* essential to chip set detection */ + +#undef WOLFSSL_ESPIDF +#undef WOLFSSL_ESP32 +#undef WOLFSSL_ESPWROOM32SE +#undef WOLFSSL_ESP32 +#undef WOLFSSL_ESP8266 + +#define WOLFSSL_ESPIDF + +/* The Espressif sdkconfig will have chipset info. +** +** Possible values: +** +** CONFIG_IDF_TARGET_ESP32 +** CONFIG_IDF_TARGET_ESP32S2 +** CONFIG_IDF_TARGET_ESP32S3 +** CONFIG_IDF_TARGET_ESP32C3 +** CONFIG_IDF_TARGET_ESP32C6 +*/ + +/* Optionally enable some wolfSSH settings */ +#ifdef ESP_ENABLE_WOLFSSH + /* The default SSH Windows size is massive for an embedded target. Limit it: */ + #define DEFAULT_WINDOW_SZ 2000 + + /* These may be defined in cmake for other examples: */ + #undef WOLFSSH_TERM + #define WOLFSSH_TERM + + #undef DEBUG_WOLFSSH + #define DEBUG_WOLFSSH + + #undef WOLFSSL_KEY_GEN + #define WOLFSSL_KEY_GEN + + #undef WOLFSSL_PTHREADS + #define WOLFSSL_PTHREADS + + #define WOLFSSH_TEST_SERVER + #define WOLFSSH_TEST_THREADING + +#endif /* ESP_ENABLE_WOLFSSH */ + +/* when you want to use SINGLE THREAD */ +/* #define SINGLE_THREADED */ + +/* + * choose ONE of these Espressif chips to define: + * + * WOLFSSL_ESP32 + * WOLFSSL_ESPWROOM32SE + * WOLFSSL_ESP8266 + */ + +#define WOLFSSL_ESP32 + +/* optionally turn off SHA512/224 SHA512/256 */ +/* #define WOLFSSL_NOSHA512_224 */ +/* #define WOLFSSL_NOSHA512_256 */ + +/* when you want to use SINGLE THREAD. Note Default ESP-IDF is FreeRTOS */ +/* #define SINGLE_THREADED */ + +/* When you don't want to use the old SHA */ +/* #define NO_SHA */ +/* #define NO_OLD_TLS */ + +#define BENCH_EMBEDDED +#define USE_CERT_BUFFERS_2048 + +#define NO_OLD_TLS +/* TLS 1.3 + #define WOLFSSL_TLS13 + #define HAVE_TLS_EXTENSIONS + #define WC_RSA_PSS + #define HAVE_SUPPORTED_CURVES +*/ + +#define HAVE_HKDF +#define HAVE_AEAD + +#define NO_FILESYSTEM + +#define HAVE_AESGCM + +#define WOLFSSL_RIPEMD +/* when you want to use SHA224 */ +/* #define WOLFSSL_SHA224 */ + + +/* when you want to use SHA384 */ +/* #define WOLFSSL_SHA384 */ + +/* #define WOLFSSL_SHA3 */ + +#define WOLFSSL_SHA512 + +#define MY_USE_ECC 1 +#define MY_USE_RSA 0 + +/* We can use either or both ECC and RSA, but must use at least one. */ +#if MY_USE_ECC || MY_USE_RSA + #if MY_USE_ECC + /* ---- ECDSA / ECC ---- */ + #define HAVE_ECC + #define HAVE_CURVE25519 + #define HAVE_ED25519 + + /* + #define HAVE_ECC384 + #define CURVE25519_SMALL + */ + #else + #define WOLFSSH_NO_ECC + /* WOLFSSH_NO_ECDSA is typically defined automatically, + * here for clarity: */ + #define WOLFSSH_NO_ECDSA + #endif + + #if MY_USE_RSA + /* ---- RSA ----- */ + /* #define RSA_LOW_MEM */ + + /* DH disabled by default, needed if ECDSA/ECC also turned off */ + #define HAVE_DH + #else + #define WOLFSSH_NO_RSA + #endif +#else + #error "Either RSA or ECC must be enabled" +#endif + + +/* when you want to use pkcs7 */ +/* #define HAVE_PKCS7 */ + +#if defined(HAVE_PKCS7) + #define HAVE_AES_KEYWRAP + #define HAVE_X963_KDF + #define WOLFSSL_AES_DIRECT +#endif + +/* when you want to use aes counter mode */ +/* #define WOLFSSL_AES_DIRECT */ +/* #define WOLFSSL_AES_COUNTER */ + +/* debug options */ +/* #define DEBUG_WOLFSSL */ +/* #define WOLFSSL_ESP32_CRYPT_DEBUG */ +/* #define WOLFSSL_ATECC508A_DEBUG */ + +/* date/time */ +/* if it cannot adjust time in the device, */ +/* enable macro below */ +/* #define NO_ASN_TIME */ +/* #define XTIME time */ + +/* adjust wait-timeout count if you see timeout in RSA HW acceleration */ +#define ESP_RSA_TIMEOUT_CNT 0x249F00 + + +/* USE_FAST_MATH is default */ +#define USE_FAST_MATH + +/***** Use SP_MATH *****/ +/* #undef USE_FAST_MATH */ +/* #define SP_MATH */ +/* #define WOLFSSL_SP_MATH_ALL */ +/* #define WOLFSSL_SP_RISCV32 */ + +/***** Use Integer Heap Math *****/ +/* #undef USE_FAST_MATH */ +/* #define USE_INTEGER_HEAP_MATH */ + + +#define WOLFSSL_SMALL_STACK + +/* The ESP32 has some detailed statup information available:*/ +#define HAVE_VERSION_EXTENDED_INFO + +/* optional SM4 Ciphers. See https://github.com/wolfSSL/wolfsm */ +/* +#define WOLFSSL_SM2 +#define WOLFSSL_SM3 +#define WOLFSSL_SM4 +*/ + +#if defined(WOLFSSL_SM2) || defined(WOLFSSL_SM3) || defined(WOLFSSL_SM4) + /* SM settings, possible cipher suites: + + TLS13-AES128-GCM-SHA256 + TLS13-CHACHA20-POLY1305-SHA256 + TLS13-SM4-GCM-SM3 + TLS13-SM4-CCM-SM3 + + #define WOLFSSL_ESP32_CIPHER_SUITE "TLS13-SM4-GCM-SM3" + #define WOLFSSL_ESP32_CIPHER_SUITE "TLS13-SM4-CCM-SM3" + #define WOLFSSL_ESP32_CIPHER_SUITE "ECDHE-ECDSA-SM4-CBC-SM3" + #define WOLFSSL_ESP32_CIPHER_SUITE "ECDHE-ECDSA-SM4-GCM-SM3" + #define WOLFSSL_ESP32_CIPHER_SUITE "ECDHE-ECDSA-SM4-CCM-SM3" + #define WOLFSSL_ESP32_CIPHER_SUITE "TLS13-SM4-GCM-SM3:" \ + "TLS13-SM4-CCM-SM3:" + */ + + #undef WOLFSSL_BASE16 + #define WOLFSSL_BASE16 /* required for WOLFSSL_SM2 */ + + #undef WOLFSSL_SM4_ECB + #define WOLFSSL_SM4_ECB + + #undef WOLFSSL_SM4_CBC + #define WOLFSSL_SM4_CBC + + #undef WOLFSSL_SM4_CTR + #define WOLFSSL_SM4_CTR + + #undef WOLFSSL_SM4_GCM + #define WOLFSSL_SM4_GCM + + #undef WOLFSSL_SM4_CCM + #define WOLFSSL_SM4_CCM + + #define HAVE_POLY1305 + #define HAVE_CHACHA + + #undef HAVE_AESGCM + #define HAVE_AESGCM +#else + /* default settings */ + #define USE_CERT_BUFFERS_2048 +#endif + +/* esp32-wroom-32se specific definition */ +#if defined(WOLFSSL_ESPWROOM32SE) + #define WOLFSSL_ATECC508A + #define HAVE_PK_CALLBACKS + /* when you want to use a custom slot allocation for ATECC608A */ + /* unless your configuration is unusual, you can use default */ + /* implementation. */ + /* #define CUSTOM_SLOT_ALLOCATION */ +#endif + +/* Default is HW enabled unless turned off. +** Uncomment these lines to force SW instead of HW acceleration */ + +#if defined(CONFIG_IDF_TARGET_ESP32) || defined(WOLFSSL_ESPWROOM32SE) + /* wolfSSL HW Acceleration supported on ESP32. Uncomment to disable: */ + /* #define NO_ESP32_CRYPT */ + /* #define NO_WOLFSSL_ESP32_CRYPT_HASH */ + /* #define NO_WOLFSSL_ESP32_CRYPT_AES */ + /* #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI */ + /* #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_MP_MUL */ + /* #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_MULMOD */ + /* #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_EXPTMOD */ + + /* These are defined automatically in esp32-crypt.h, here for clarity: */ + /* no SHA224 HW on ESP32 */ + #define NO_WOLFSSL_ESP32_CRYPT_HASH_SHA224 + + /* 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 */ + #define EPS_RSA_EXPT_XBTIS 32 + + /* X and Y of X * Y mod P greater than */ + #undef ESP_RSA_MULM_BITS + #define ESP_RSA_MULM_BITS 16 + + /***** END CONFIG_IDF_TARGET_ESP32 *****/ + +#elif defined(CONFIG_IDF_TARGET_ESP32S2) + /* wolfSSL HW Acceleration supported on ESP32-S2. Uncomment to disable: */ + /* #define NO_ESP32_CRYPT */ + /* #define NO_WOLFSSL_ESP32_CRYPT_HASH */ + /* Note: There's no AES192 HW on the ESP32-S2; falls back to SW */ + /* #define NO_WOLFSSL_ESP32_CRYPT_AES */ + /* #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI */ + /* #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_MP_MUL */ + /* #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_MULMOD */ + /* #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_EXPTMOD */ + /***** END CONFIG_IDF_TARGET_ESP32S2 *****/ + +#elif defined(CONFIG_IDF_TARGET_ESP32S3) + /* wolfSSL HW Acceleration supported on ESP32-S3. Uncomment to disable: */ + /* #define NO_ESP32_CRYPT */ + /* #define NO_WOLFSSL_ESP32_CRYPT_HASH */ + /* Note: There's no AES192 HW on the ESP32-S3; falls back to SW */ + /* #define NO_WOLFSSL_ESP32_CRYPT_AES */ + /* #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI */ + /* #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_MP_MUL */ + /* #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_MULMOD */ + /* #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_EXPTMOD */ + /***** END CONFIG_IDF_TARGET_ESP32S3 *****/ + +#elif defined(CONFIG_IDF_TARGET_ESP32C2) || \ + defined(CONFIG_IDF_TARGET_ESP8684) + /* ESP8684 is essentially ESP32-C2 chip + flash embedded together in a + * single QFN 4x4 mm package. Out of released documentation, Technical + * Reference Manual as well as ESP-IDF Programming Guide is applicable + * to both ESP32-C2 and ESP8684. + * + * See: https://www.esp32.com/viewtopic.php?f=5&t=27926#:~:text=ESP8684%20is%20essentially%20ESP32%2DC2,both%20ESP32%2DC2%20and%20ESP8684. */ + + /* wolfSSL HW Acceleration supported on ESP32-C2. Uncomment to disable: */ + /* #define NO_ESP32_CRYPT */ + /* #define NO_WOLFSSL_ESP32_CRYPT_HASH */ /* to disable all SHA HW */ + + /* These are defined automatically in esp32-crypt.h, here for clarity */ + #define NO_WOLFSSL_ESP32_CRYPT_HASH_SHA384 /* no SHA384 HW on C2 */ + #define NO_WOLFSSL_ESP32_CRYPT_HASH_SHA512 /* no SHA512 HW on C2 */ + + /* There's no AES or RSA/Math accelerator on the ESP32-C2 + * Auto defined with NO_WOLFSSL_ESP32_CRYPT_RSA_PRI, for clarity: */ + #define NO_WOLFSSL_ESP32_CRYPT_AES + #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI + #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_MP_MUL + #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_MULMOD + #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_EXPTMOD + /***** END CONFIG_IDF_TARGET_ESP32C2 *****/ + +#elif defined(CONFIG_IDF_TARGET_ESP32C3) + /* wolfSSL HW Acceleration supported on ESP32-C3. Uncomment to disable: */ + + /* #define NO_ESP32_CRYPT */ + /* #define NO_WOLFSSL_ESP32_CRYPT_HASH */ /* to disable all SHA HW */ + + /* These are defined automatically in esp32-crypt.h, here for clarity: */ + #define NO_WOLFSSL_ESP32_CRYPT_HASH_SHA384 /* no SHA384 HW on C6 */ + #define NO_WOLFSSL_ESP32_CRYPT_HASH_SHA512 /* no SHA512 HW on C6 */ + + /* #define NO_WOLFSSL_ESP32_CRYPT_AES */ + /* #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI */ + /* #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_MP_MUL */ + /* #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_MULMOD */ + /* #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_EXPTMOD */ + /***** END CONFIG_IDF_TARGET_ESP32C3 *****/ + +#elif defined(CONFIG_IDF_TARGET_ESP32C6) + /* wolfSSL HW Acceleration supported on ESP32-C6. Uncomment to disable: */ + + /* #define NO_ESP32_CRYPT */ + /* #define NO_WOLFSSL_ESP32_CRYPT_HASH */ + /* These are defined automatically in esp32-crypt.h, here for clarity: */ + #define NO_WOLFSSL_ESP32_CRYPT_HASH_SHA384 /* no SHA384 HW on C6 */ + #define NO_WOLFSSL_ESP32_CRYPT_HASH_SHA512 /* no SHA512 HW on C6 */ + + /* #define NO_WOLFSSL_ESP32_CRYPT_AES */ + /* #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI */ + /* #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_MP_MUL */ + /* #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_MULMOD */ + /* #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_EXPTMOD */ + /***** END CONFIG_IDF_TARGET_ESP32C6 *****/ + +#elif defined(CONFIG_IDF_TARGET_ESP32H2) + /* wolfSSL Hardware Acceleration not yet implemented */ + #define NO_ESP32_CRYPT + #define NO_WOLFSSL_ESP32_CRYPT_HASH + #define NO_WOLFSSL_ESP32_CRYPT_AES + #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI + /***** END CONFIG_IDF_TARGET_ESP32H2 *****/ + +#elif defined(CONFIG_IDF_TARGET_ESP8266) + /* TODO: Revisit ESP8266 */ + #define NO_ESP32_CRYPT + #define NO_WOLFSSL_ESP32_CRYPT_HASH + #define NO_WOLFSSL_ESP32_CRYPT_AES + #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI + /***** END CONFIG_IDF_TARGET_ESP266 *****/ + +#elif defined(CONFIG_IDF_TARGET_ESP8684) + /* There's no Hardware Acceleration available on ESP8684 */ + #define NO_ESP32_CRYPT + #define NO_WOLFSSL_ESP32_CRYPT_HASH + #define NO_WOLFSSL_ESP32_CRYPT_AES + #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI + /***** END CONFIG_IDF_TARGET_ESP8684 *****/ + +#else + /* Anything else encountered, disable HW accleration */ + #define NO_ESP32_CRYPT + #define NO_WOLFSSL_ESP32_CRYPT_HASH + #define NO_WOLFSSL_ESP32_CRYPT_AES + #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI +#endif /* CONFIG_IDF_TARGET Check */ + +/* Debug options: + +#define ESP_VERIFY_MEMBLOCK +#define DEBUG_WOLFSSL +#define DEBUG_WOLFSSL_VERBOSE +#define DEBUG_WOLFSSL_SHA_MUTEX +#define WOLFSSL_ESP32_CRYPT_DEBUG +#define WOLFSSL_ESP32_CRYPT_HASH_SHA224_DEBUG +#define NO_RECOVER_SOFTWARE_CALC +#define WOLFSSL_TEST_STRAY 1 +#define USE_ESP_DPORT_ACCESS_READ_BUFFER +#define WOLFSSL_ESP32_HW_LOCK_DEBUG +#define WOLFSSL_DEBUG_ESP_RSA_MULM_BITS +#define ESP_DISABLE_HW_TASK_LOCK +*/ + +/* Pause in a loop rather than exit. */ +#define WOLFSSL_ESPIDF_ERROR_PAUSE + +/* #define WOLFSSL_HW_METRICS */ + +/* for test.c */ +/* #define HASH_SIZE_LIMIT */ + +/* Optionally turn off HW math checks */ +/* #define NO_HW_MATH_TEST */ + +/* Optionally include alternate HW test library: alt_hw_test.h */ +/* When enabling, the ./components/wolfssl/CMakeLists.txt file + * will need the name of the library in the idf_component_register + * for the PRIV_REQUIRES list. */ +/* #define INCLUDE_ALT_HW_TEST */ + +/* optionally turn off individual math HW acceleration features */ + +/* Turn off Large Number ESP32 HW Multiplication: +** [Z = X * Y] in esp_mp_mul() */ +/* #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_MP_MUL */ + +/* Turn off Large Number ESP32 HW Modular Exponentiation: +** [Z = X^Y mod M] in esp_mp_exptmod() */ +/* #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_EXPTMOD */ + +/* Turn off Large Number ESP32 HW Modular Multiplication +** [Z = X * Y mod M] in esp_mp_mulmod() */ +/* #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_MULMOD */ + +#define WOLFSSL_PUBLIC_MP /* used by benchmark */ +#define USE_CERT_BUFFERS_2048 + +/* when turning on ECC508 / ECC608 support +#define WOLFSSL_ESPWROOM32SE +#define HAVE_PK_CALLBACKS +#define WOLFSSL_ATECC508A +#define ATCA_WOLFSSL +*/ + +/* optional SM4 Ciphers. See https://github.com/wolfSSL/wolfsm +#define WOLFSSL_SM2 +#define WOLFSSL_SM3 +#define WOLFSSL_SM4 +*/ + +#if defined(WOLFSSL_SM2) || defined(WOLFSSL_SM3) || defined(WOLFSSL_SM4) + #include + #define CTX_CA_CERT root_sm2 + #define CTX_CA_CERT_SIZE sizeof_root_sm2 + #define CTX_CA_CERT_TYPE WOLFSSL_FILETYPE_PEM + #define CTX_SERVER_CERT server_sm2 + #define CTX_SERVER_CERT_SIZE sizeof_server_sm2 + #define CTX_SERVER_CERT_TYPE WOLFSSL_FILETYPE_PEM + #define CTX_SERVER_KEY server_sm2_priv + #define CTX_SERVER_KEY_SIZE sizeof_server_sm2_priv + #define CTX_SERVER_KEY_TYPE WOLFSSL_FILETYPE_PEM + + #undef WOLFSSL_BASE16 + #define WOLFSSL_BASE16 +#else + #define USE_CERT_BUFFERS_2048 + #define USE_CERT_BUFFERS_256 + #define CTX_CA_CERT ca_cert_der_2048 + #define CTX_CA_CERT_SIZE sizeof_ca_cert_der_2048 + #define CTX_CA_CERT_TYPE WOLFSSL_FILETYPE_ASN1 + #define CTX_SERVER_CERT server_cert_der_2048 + #define CTX_SERVER_CERT_SIZE sizeof_server_cert_der_2048 + #define CTX_SERVER_CERT_TYPE WOLFSSL_FILETYPE_ASN1 + #define CTX_SERVER_KEY server_key_der_2048 + #define CTX_SERVER_KEY_SIZE sizeof_server_key_der_2048 + #define CTX_SERVER_KEY_TYPE WOLFSSL_FILETYPE_ASN1 +#endif + +/* See settings.h for some of the possible hardening options: + * + * #define NO_ESPIDF_DEFAULT + * #define WC_NO_CACHE_RESISTANT + * #define WC_AES_BITSLICED + * #define HAVE_AES_ECB + * #define HAVE_AES_DIRECT + */ diff --git a/ide/Espressif/ESP-IDF/examples/wolfssh_template/main/CMakeLists.txt b/ide/Espressif/ESP-IDF/examples/wolfssh_template/main/CMakeLists.txt new file mode 100644 index 000000000..9ae9d6bf7 --- /dev/null +++ b/ide/Espressif/ESP-IDF/examples/wolfssh_template/main/CMakeLists.txt @@ -0,0 +1,154 @@ +# [wolfSSL Project]/main/CMakeLists.txt +# +# Copyright (C) 2006-2023 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 2 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 this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA +# +# cmake for WOLFSSH Espressif projects +# +# See https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/build-system.html +# wolfSSL wolfSSH Espressif Example Project/main/CMakeLists.txt +# v1.0 +# +message(STATUS "main cmake found WOLFSSL_COMPONENT_NAME = ${WOLFSSL_COMPONENT_NAME}") + +if(WIN32) + # Windows-specific configuration here + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DWOLFSSL_CMAKE_SYSTEM_NAME_WINDOWS") + message("Detected Windows") +endif() +if(CMAKE_HOST_UNIX) + message("Detected UNIX") +endif() +if(APPLE) + message("Detected APPLE") +endif() +if(CMAKE_HOST_UNIX AND (NOT APPLE) AND EXISTS "/proc/sys/fs/binfmt_misc/WSLInterop") + # Windows-specific configuration here + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DWOLFSSL_CMAKE_SYSTEM_NAME_WSL") + message("Detected WSL") +endif() +if(CMAKE_HOST_UNIX AND (NOT APPLE) AND (NOT WIN32)) + # Windows-specific configuration here + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DWOLFSSL_CMAKE_SYSTEM_NAME_LINUX") + message("Detected Linux") +endif() +if(APPLE) + # Windows-specific configuration here + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DWOLFSSL_CMAKE_SYSTEM_NAME_APPLE") + message("Detected Apple") +endif() +set (git_cmd "git") + +if( EXISTS "${CMAKE_HOME_DIRECTORY}/components/wolfssl/" AND EXISTS "$ENV{IDF_PATH}/components/wolfssl/" ) + # + # wolfSSL found in both ESP-IDF and local project - needs to be resolved by user + # + message(STATUS "") + message(STATUS "WARNING: Found components/wolfssl in both local project and IDF_PATH") + message(STATUS "") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DWOLFSSL_MULTI_INSTALL_WARNING") +endif() + +if( "$ENV{IDF_COMPONENT_REGISTRY_URL}" STREQUAL "https://components-staging.espressif.com" ) + if( ("${managed_components}" STREQUAL "") AND ("${component_manager_interface_version}" STREQUAL "") ) + # We've found a staging component, but did not detect the component manager + if(EXISTS ${CMAKE_CURRENT_LIST_DIR}/../components/mywolfssh/CMakeLists.txt) + # This is typically during publish-time build test + message(STATUS "Set name mywolfssh (1)") + set(WOLFSSL_COMPONENT_NAME "mywolfssl") + set(WOLFSSH_COMPONENT_NAME "mywolfssh") + else() + if(EXISTS ${CMAKE_CURRENT_LIST_DIR}/../managed_components/gojimmypi__mywolfmqtt/CMakeLists.txt) + # This is typically upon creating a project from managed component examples + message(STATUS "Set name mywolfssh (2)") + set(WOLFSSL_COMPONENT_NAME "mywolfssl") + set(WOLFSSH_COMPONENT_NAME "mywolfssh") + else() + message(STATUS "Set name wolfmqtt (1) CMAKE_CURRENT_LIST_DIR = ${CMAKE_CURRENT_LIST_DIR}") + set(WOLFSSL_COMPONENT_NAME "wolfssl") + set(WOLFSSH_COMPONENT_NAME "wolfssh") + endif() + endif() + else() + message(STATUS "Set name mywolfssh (3)") + set(WOLFSSL_COMPONENT_NAME "mywolfssl") + set(WOLFSSH_COMPONENT_NAME "mywolfssh") + endif() +else() + message(STATUS "Set name wolfssh (2)") + set(WOLFSSL_COMPONENT_NAME "wolfssl") + set(WOLFSSH_COMPONENT_NAME "wolfssh") +endif() + +## register_component() +idf_component_register(SRCS main.c + INCLUDE_DIRS "." "./include") +# + +# +# LIBWOLFSSL_SAVE_INFO(VAR_OUPUT THIS_VAR VAR_RESULT) +# +# Save the THIS_VAR as a string in a macro called VAR_OUPUT +# +# VAR_OUPUT: the name of the macro to define +# THIS_VAR: the OUTPUT_VARIABLE result from a execute_process() +# VAR_RESULT: the RESULT_VARIABLE from a execute_process(); "0" if successful. +# +function ( LIBWOLFSSL_SAVE_INFO VAR_OUPUT THIS_VAR VAR_RESULT ) + # is the RESULT_VARIABLE output value 0? If so, IS_VALID_VALUE is true. + string(COMPARE EQUAL "${VAR_RESULT}" "0" IS_VALID_VALUE) + + # if we had a successful operation, save the THIS_VAR in VAR_OUPUT + if(${IS_VALID_VALUE}) + # strip newline chars in THIS_VAR parameter and save in VAR_VALUE + string(REPLACE "\n" "" VAR_VALUE ${THIS_VAR}) + + # we'll could percolate the value to the parent for possible later use + # set(${VAR_OUPUT} ${VAR_VALUE} PARENT_SCOPE) + + # but we're only using it here in this function + set(${VAR_OUPUT} ${VAR_VALUE}) + + # we'll print what we found to the console + message(STATUS "Found ${VAR_OUPUT}=${VAR_VALUE}") + + # the interesting part is defining the VAR_OUPUT name a value to use in the app + add_definitions(-D${VAR_OUPUT}=\"${VAR_VALUE}\") + else() + # if we get here, check the execute_process command and parameters. + message(STATUS "LIBWOLFSSL_SAVE_INFO encountered a non-zero VAR_RESULT") + set(${VAR_OUPUT} "Unknown") + endif() +endfunction() # LIBWOLFSSL_SAVE_INFO + +if(NOT CMAKE_BUILD_EARLY_EXPANSION) + # LIBWOLFSSL_VERSION_GIT_HASH + execute_process(COMMAND ${git_cmd} "rev-parse" "HEAD" OUTPUT_VARIABLE TMP_OUT RESULT_VARIABLE TMP_RES ERROR_QUIET ) + LIBWOLFSSL_SAVE_INFO(LIBWOLFSSL_VERSION_GIT_HASH "${TMP_OUT}" "${TMP_RES}") + + # LIBWOLFSSL_VERSION_GIT_SHORT_HASH + execute_process(COMMAND ${git_cmd} "rev-parse" "--short" "HEAD" OUTPUT_VARIABLE TMP_OUT RESULT_VARIABLE TMP_RES ERROR_QUIET ) + LIBWOLFSSL_SAVE_INFO(LIBWOLFSSL_VERSION_GIT_SHORT_HASH "${TMP_OUT}" "${TMP_RES}") + + # LIBWOLFSSL_VERSION_GIT_HASH_DATE + execute_process(COMMAND ${git_cmd} "show" "--no-patch" "--no-notes" "--pretty=\'\%cd\'" OUTPUT_VARIABLE TMP_OUT RESULT_VARIABLE TMP_RES ) + LIBWOLFSSL_SAVE_INFO(LIBWOLFSSL_VERSION_GIT_HASH_DATE "${TMP_OUT}" "${TMP_RES}") +endif() + +message(STATUS "") + diff --git a/ide/Espressif/ESP-IDF/examples/wolfssh_template/main/include/main.h b/ide/Espressif/ESP-IDF/examples/wolfssh_template/main/include/main.h new file mode 100644 index 000000000..7e07ec1df --- /dev/null +++ b/ide/Espressif/ESP-IDF/examples/wolfssh_template/main/include/main.h @@ -0,0 +1,38 @@ +/* template main.h + * + * Copyright (C) 2006-2023 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL 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 2 of the License, or + * (at your option) any later version. + * + * wolfSSL 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ +#ifndef _MAIN_H_ +#define _MAIN_H_ + +/* Espressif libraries */ +#include "sdkconfig.h" +#include +#include + +/* wolfSSL */ +#include "user_settings.h" /* always include wolfSSL user_settings.h first */ +#include +#include + +/* wolfSSH */ +#include +#include + +#endif diff --git a/ide/Espressif/ESP-IDF/examples/wolfssh_template/main/main.c b/ide/Espressif/ESP-IDF/examples/wolfssh_template/main/main.c new file mode 100644 index 000000000..6204cc398 --- /dev/null +++ b/ide/Espressif/ESP-IDF/examples/wolfssh_template/main/main.c @@ -0,0 +1,79 @@ +/* main.c + * + * Copyright (C) 2006-2023 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL 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 2 of the License, or + * (at your option) any later version. + * + * wolfSSL 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ +#include "main.h" + +/* actual working example would include WiFi & time libraries here */ + +static const char* const TAG = "My Project"; + +void app_main(void) +{ + ESP_LOGI(TAG, "------------ wolfSSL wolfSSH template Example ----------"); + ESP_LOGI(TAG, "--------------------------------------------------------"); + ESP_LOGI(TAG, "--------------------------------------------------------"); + ESP_LOGI(TAG, "---------------------- BEGIN MAIN ----------------------"); + ESP_LOGI(TAG, "--------------------------------------------------------"); + ESP_LOGI(TAG, "--------------------------------------------------------"); + + ESP_LOGI(TAG, "Hello wolfSSL!"); + +#ifdef DEBUG_WOLFSSH + wolfSSH_Debugging_ON(); +#else + ESP_LOGI(TAG, "DEBUG_WOLFSSH is not defined, " + "so nothing will happen for teh next statement"); +#endif + +#ifdef HAVE_VERSION_EXTENDED_INFO + esp_ShowExtendedSystemInfo(); +#endif + +#ifdef INCLUDE_uxTaskGetStackHighWaterMark + ESP_LOGI(TAG, "Stack HWM: %d", uxTaskGetStackHighWaterMark(NULL)); + + ESP_LOGI(TAG, "Stack used: %d", CONFIG_ESP_MAIN_TASK_STACK_SIZE + - (uxTaskGetStackHighWaterMark(NULL))); +#endif + +/* the simplest check of the wolfSSL library presence: */ +#ifdef LIBWOLFSSL_VERSION_STRING + ESP_LOGI(TAG, ""); + ESP_LOGI(TAG, "Found wolfSSL Version %s\n", LIBWOLFSSL_VERSION_STRING); +#else + ESP_LOGW(TAG, "Warning: Could not find wolfSSL Version"); +#endif + +/* the simplest check of the wolfSSH library presence: */ +#ifdef LIBWOLFSSH_VERSION_STRING + ESP_LOGI(TAG, ""); + ESP_LOGI(TAG, "Found wolfSSH Version %s\n", LIBWOLFSSH_VERSION_STRING); + wolfSSH_Log(WS_LOG_INFO, "[wolfssh] Hello World!"); +#else + ESP_LOGW(TAG, "Warning: Could not find wolfSSH Version"); +#endif + +/* actual working example would initialize WiFi & time libraries here */ + + ESP_LOGI(TAG, "\n\nDone!\n\n" + "If running from idf.py monitor, press twice: Ctrl+]\n\n" + "WOLFSSL_COMPLETE\n" /* exit keyword for wolfssl_monitor.py */ + ); +} /* app_main */ diff --git a/ide/Espressif/ESP-IDF/examples/wolfssh_template/partitions_singleapp_large.csv b/ide/Espressif/ESP-IDF/examples/wolfssh_template/partitions_singleapp_large.csv new file mode 100644 index 000000000..a9c373bec --- /dev/null +++ b/ide/Espressif/ESP-IDF/examples/wolfssh_template/partitions_singleapp_large.csv @@ -0,0 +1,31 @@ +# to view: idf.py partition-table +# +# ESP-IDF Partition Table +# Name, Type, SubType, Offset, Size, Flags +nvs, data, nvs, 0x9000, 24K, +phy_init,data, phy, 0xf000, 4K, +factory, app, factory, 0x10000, 1500K, + + +# For other settings, see: +# https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/partition-tables.html#creating-custom-tables +# +# Here is the summary printed for the "Single factory app, no OTA" configuration: +# +# # ESP-IDF Partition Table +# # Name, Type, SubType, Offset, Size, Flags +# nvs, data, nvs, 0x9000, 0x6000, +# phy_init, data, phy, 0xf000, 0x1000, +# factory, app, factory, 0x10000, 1M, +# +# +# Here is the summary printed for the "Factory app, two OTA definitions" configuration: +# +# # ESP-IDF Partition Table +# # Name, Type, SubType, Offset, Size, Flags +# nvs, data, nvs, 0x9000, 0x4000, +# otadata, data, ota, 0xd000, 0x2000, +# phy_init, data, phy, 0xf000, 0x1000, +# factory, app, factory, 0x10000, 1M, +# ota_0, app, ota_0, 0x110000, 1M, +# ota_1, app, ota_1, 0x210000, 1M, diff --git a/ide/Espressif/ESP-IDF/examples/wolfssh_template/sdkconfig.defaults b/ide/Espressif/ESP-IDF/examples/wolfssh_template/sdkconfig.defaults new file mode 100644 index 000000000..109246181 --- /dev/null +++ b/ide/Espressif/ESP-IDF/examples/wolfssh_template/sdkconfig.defaults @@ -0,0 +1,38 @@ +# This file was generated using idf.py save-defconfig. It can be edited manually. +# Espressif IoT Development Framework (ESP-IDF) Project Minimal Configuration + +CONFIG_FREERTOS_HZ=1000 +CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y + +# +# Default main stack size +# +# This is typically way bigger than needed for stack size. See user_settings.h +# +CONFIG_ESP_MAIN_TASK_STACK_SIZE=10500 + +# Legacy stack size for older ESP-IDF versions +CONFIG_MAIN_TASK_STACK_SIZE=10500 + +# +# Compiler options +# +CONFIG_COMPILER_OPTIMIZATION_DEFAULT=y +CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE=y +CONFIG_COMPILER_OPTIMIZATION_ASSERTION_LEVEL=2 +CONFIG_COMPILER_HIDE_PATHS_MACROS=y +CONFIG_COMPILER_STACK_CHECK_MODE_NORM=y +CONFIG_COMPILER_STACK_CHECK=y + +# +# Partition Table +# +# CONFIG_PARTITION_TABLE_SINGLE_APP is not set +CONFIG_PARTITION_TABLE_SINGLE_APP_LARGE=y +# CONFIG_PARTITION_TABLE_TWO_OTA is not set +# CONFIG_PARTITION_TABLE_CUSTOM is not set +CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" +CONFIG_PARTITION_TABLE_FILENAME="partitions_singleapp_large.csv" +CONFIG_PARTITION_TABLE_OFFSET=0x8000 +CONFIG_PARTITION_TABLE_MD5=y +# end of Partition Table From 76dedcb51589b7ab91b8f8eaf5b2c4a02a618c44 Mon Sep 17 00:00:00 2001 From: gojimmypi Date: Fri, 6 Oct 2023 16:23:08 -0700 Subject: [PATCH 4/5] no WSL/Windows git hooks from autogen.sh --- autogen.sh | 43 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 40 insertions(+), 3 deletions(-) diff --git a/autogen.sh b/autogen.sh index e1b5bf796..86a4be674 100755 --- a/autogen.sh +++ b/autogen.sh @@ -2,10 +2,47 @@ # # Create configure and makefile stuff... +# Check environment +if [ -n "$WSL_DISTRO_NAME" ]; then + # we found a non-blank WSL environment distro name + current_path="$(pwd)" + pattern="/mnt/?" + if [ "$(echo "$current_path" | grep -E "^$pattern")" ]; then + # if we are in WSL and shared Windows file system, 'ln' does not work. + no_links=true + else + no_links= + fi +fi + # Git hooks should come before autoreconf. -if test -d .git -then - mkdir -p .git/hooks && ln -sf ../../scripts/pre-commit.sh .git/hooks/pre-commit +if [ -d .git ]; then + if [ ! -d .git/hooks ]; then + mkdir .git/hooks || exit $? + fi + + if [ -n "$no_links" ]; then + echo "Linux ln does not work on shared Windows file system in WSL." + if [ ! -e .git/hooks/pre-commit ]; then + echo "The pre-commit.sh file will not be copied to .git/hooks/pre-commit" + # shell scripts do not work on Windows; TODO create equivalent batch file + # cp ./pre-commit.sh .git/hooks/pre-commit || exit $? + fi + # unlike wolfssl, wolfssh is not using pre-push.sh at this time. Enable as needed: + # if [ ! -e .git/hooks/pre-push ]; then + # echo "The pre-push.sh file will not be copied to .git/hooks/pre-commit" + # # shell scripts do not work on Windows; TODO create equivalent batch file + # # cp ./pre-push.sh .git/hooks/pre-push || exit $? + # fi + else + if [ ! -e .git/hooks/pre-commit ]; then + ln -sf ../../scripts/pre-commit.sh .git/hooks/pre-commit || exit $? + fi + # unlike wolfssl, wolfssh is not using pre-push.sh at this time Enable as needed: + # if [ ! -e .git/hooks/pre-push ]; then + # ln -s ../../pre-push.sh .git/hooks/pre-push || exit $? + # fi + fi fi # If this is a source checkout then call autoreconf with error as well From 80a21ccc090ec5a93fccc81e69c7fdb754423fe6 Mon Sep 17 00:00:00 2001 From: JacobBarthelmeh Date: Tue, 5 Dec 2023 16:33:13 -0700 Subject: [PATCH 5/5] print out log on fail and remove print out from alarm --- apps/wolfsshd/test/sshd_login_grace_test.sh | 6 +++++- apps/wolfsshd/wolfsshd.c | 12 +++++++++--- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/apps/wolfsshd/test/sshd_login_grace_test.sh b/apps/wolfsshd/test/sshd_login_grace_test.sh index 9e498d8cd..00b950ba9 100755 --- a/apps/wolfsshd/test/sshd_login_grace_test.sh +++ b/apps/wolfsshd/test/sshd_login_grace_test.sh @@ -47,14 +47,18 @@ if [ "$RESULT" != 0 ]; then exit 1 fi +# attempt clearing out stdin from previous echo/grep +read -t 1 -n 1000 discard + # test grace login timeout by stalling on password prompt -timeout 7 "$TEST_CLIENT" -u "$USER" -h "$TEST_HOST" -p "$TEST_PORT" -t +timeout --foreground 7 "$TEST_CLIENT" -u "$USER" -h "$TEST_HOST" -p "$TEST_PORT" -t popd cat ./log.txt | grep "Failed login within grace period" RESULT=$? if [ "$RESULT" != 0 ]; then echo "FAIL: Grace period not hit" + cat ./log.txt exit 1 fi diff --git a/apps/wolfsshd/wolfsshd.c b/apps/wolfsshd/wolfsshd.c index b8b3673f7..896723e57 100644 --- a/apps/wolfsshd/wolfsshd.c +++ b/apps/wolfsshd/wolfsshd.c @@ -1467,7 +1467,6 @@ static __thread int timeOut = 0; #endif static void alarmCatch(int signum) { - wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Failed login within grace period"); timeOut = 1; (void)signum; } @@ -1553,7 +1552,14 @@ static void* HandleConnection(void* arg) error = WS_FATAL_ERROR; } + wolfSSH_Log(WS_LOG_ERROR, + "[SSHD] grace time = %ld timeout = %d", graceTime, timeOut); if (graceTime > 0) { + if (timeOut) { + wolfSSH_Log(WS_LOG_ERROR, + "[SSHD] Failed login within grace period"); + } + #ifdef WIN32 /* @TODO SetTimer(NULL, NULL, graceTime, alarmCatch); */ #else @@ -1564,8 +1570,8 @@ static void* HandleConnection(void* arg) if (ret != WS_SUCCESS && ret != WS_SFTP_COMPLETE && ret != WS_SCP_INIT) { wolfSSH_Log(WS_LOG_ERROR, - "[SSHD] Failed to accept WOLFSSH connection from %s", - conn->ip); + "[SSHD] Failed to accept WOLFSSH connection from %s error %d", + conn->ip, ret); } }