diff --git a/ide/Espressif/ESP-IDF/examples/README.md b/ide/Espressif/ESP-IDF/examples/README.md index b310a31bc..63ebbdd7f 100644 --- a/ide/Espressif/ESP-IDF/examples/README.md +++ b/ide/Espressif/ESP-IDF/examples/README.md @@ -1 +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_server/CMakeLists.txt b/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/CMakeLists.txt similarity index 79% rename from ide/Espressif/ESP-IDF/examples/wolfssh_server/CMakeLists.txt rename to ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/CMakeLists.txt index f0cc10e98..2b754ab8f 100644 --- a/ide/Espressif/ESP-IDF/examples/wolfssh_server/CMakeLists.txt +++ b/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/CMakeLists.txt @@ -1,3 +1,27 @@ +# [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 # @@ -9,9 +33,8 @@ cmake_minimum_required(VERSION 3.16) 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") +# 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: @@ -103,4 +126,4 @@ endif() include($ENV{IDF_PATH}/tools/cmake/project.cmake) -project(wolfssh_server) +project(wolfssh_echoserver) diff --git a/ide/Espressif/ESP-IDF/examples/wolfssh_server/README.md b/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/README.md similarity index 100% rename from ide/Espressif/ESP-IDF/examples/wolfssh_server/README.md rename to ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/README.md diff --git a/ide/Espressif/ESP-IDF/examples/wolfssh_server/VisualGDB/wolfssh_server_IDF_v5.1_ESP32.sln b/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/VisualGDB/wolfssh_echoserver_IDF_v5.1_ESP32.sln similarity index 90% rename from ide/Espressif/ESP-IDF/examples/wolfssh_server/VisualGDB/wolfssh_server_IDF_v5.1_ESP32.sln rename to ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/VisualGDB/wolfssh_echoserver_IDF_v5.1_ESP32.sln index 45824c424..562cdb3f7 100644 --- a/ide/Espressif/ESP-IDF/examples/wolfssh_server/VisualGDB/wolfssh_server_IDF_v5.1_ESP32.sln +++ b/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/VisualGDB/wolfssh_echoserver_IDF_v5.1_ESP32.sln @@ -3,7 +3,7 @@ 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_server_IDF_v5.1_ESP32", "wolfssh_server_IDF_v5.1_ESP32.vgdbproj", "{EADCC9AB-72B3-4B51-A838-593E5D80DDF7}" +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 diff --git a/ide/Espressif/ESP-IDF/examples/wolfssh_server/VisualGDB/wolfssh_server_IDF_v5.1_ESP32.vgdbproj b/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/VisualGDB/wolfssh_echoserver_IDF_v5.1_ESP32.vgdbproj similarity index 100% rename from ide/Espressif/ESP-IDF/examples/wolfssh_server/VisualGDB/wolfssh_server_IDF_v5.1_ESP32.vgdbproj rename to ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/VisualGDB/wolfssh_echoserver_IDF_v5.1_ESP32.vgdbproj diff --git a/ide/Espressif/ESP-IDF/examples/wolfssh_server/components/wolfssh/CMakeLists.txt b/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/components/wolfssh/CMakeLists.txt similarity index 100% rename from ide/Espressif/ESP-IDF/examples/wolfssh_server/components/wolfssh/CMakeLists.txt rename to ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/components/wolfssh/CMakeLists.txt diff --git a/ide/Espressif/ESP-IDF/examples/wolfssh_server/components/wolfssl/CMakeLists.txt b/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/components/wolfssl/CMakeLists.txt similarity index 75% rename from ide/Espressif/ESP-IDF/examples/wolfssh_server/components/wolfssl/CMakeLists.txt rename to ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/components/wolfssl/CMakeLists.txt index 59fe55b3a..d58704b84 100644 --- a/ide/Espressif/ESP-IDF/examples/wolfssh_server/components/wolfssl/CMakeLists.txt +++ b/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/components/wolfssl/CMakeLists.txt @@ -19,19 +19,88 @@ # # cmake for wolfssl Espressif projects # -# Version 5.6.0.012 for improved manual setting of WOLFSSL_ROOT +# 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 +# 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}") @@ -74,9 +143,13 @@ function(IS_WOLFSSL_SOURCE DIRECTORY_PARAMETER RESULT) 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}}") @@ -162,17 +235,18 @@ 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 - esp_timer - driver # this will typically only be needed for wolfSSL benchmark + "${THIS_INCLUDE_TIMER}" + "${THIS_INCLUDE_DRIVER}" # this will typically only be needed for wolfSSL benchmark ) else() @@ -181,27 +255,65 @@ else() 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 - FIND_WOLFSSL_DIRECTORY(WOLFSSL_ROOT) + # 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 "NEW Found wolfssl directory at: ${WOLFSSL_ROOT}") + message(STATUS "Confirmed wolfssl directory at: ${WOLFSSL_ROOT}") else() - message(STATUS "NEW wolfssl directory not found.") + 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/") - if( ${CMAKE_PROJECT_NAME} STREQUAL "wolfssl_benchmark" ) - set(WOLFSSL_EXTRA_PROJECT_DIR "${WOLFSSL_ROOT}/wolfcrypt/benchmark") - endif() + # 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" ) - set(WOLFSSL_EXTRA_PROJECT_DIR "${WOLFSSL_ROOT}/wolfcrypt/test") + 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/\"" @@ -213,16 +325,18 @@ else() 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") - add_definitions(-DWOLFSSL_USER_SETTINGS_DIR="${WOLFSSL_PROJECT_DIR}/include/user_settings.h") + 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_RECURSE EXCLUDE_ASM ${CMAKE_SOURCE_DIR} "${WOLFSSL_ROOT}/wolfcrypt/src/*.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}") @@ -245,11 +359,13 @@ else() 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(FATAL_ERROR "Please use wolfSSL in either local project or Espressif components, but not both.") 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") @@ -299,6 +415,7 @@ else() 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" ) @@ -369,16 +486,17 @@ else() endif() endif() - + # wolfSSL-specific include directories set(COMPONENT_ADD_INCLUDEDIRS - "./include" # this is the location of wolfssl user_settings.h + "./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() @@ -387,7 +505,7 @@ else() 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\"" @@ -436,17 +554,34 @@ else() INCLUDE_DIRS "${COMPONENT_ADD_INCLUDEDIRS}" REQUIRES "${COMPONENT_REQUIRES}" EXCLUDE_SRCS "${COMPONENT_SRCEXCLUDE}" - PRIV_REQUIRES esp_timer driver # this will typically only be needed for wolfSSL benchmark + PRIV_REQUIRES + "${THIS_INCLUDE_TIMER}" + "${THIS_INCLUDE_DRIVER}" # this will typically only be needed for wolfSSL benchmark ) - # some optional diagnostics - if (1) + + # 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}) - message(STATUS "${_variableName}=${${_variableName}}") + 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") @@ -533,6 +668,8 @@ if(NOT CMAKE_BUILD_EARLY_EXPANSION) 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 "************************************************************************************************") diff --git a/ide/Espressif/ESP-IDF/examples/wolfssh_server/components/wolfssl/README.md b/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/components/wolfssl/README.md similarity index 100% rename from ide/Espressif/ESP-IDF/examples/wolfssh_server/components/wolfssl/README.md rename to ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/components/wolfssl/README.md 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_server/main/CMakeLists.txt b/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/main/CMakeLists.txt similarity index 83% rename from ide/Espressif/ESP-IDF/examples/wolfssh_server/main/CMakeLists.txt rename to ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/main/CMakeLists.txt index 46be022c2..d58c2ae1c 100644 --- a/ide/Espressif/ESP-IDF/examples/wolfssh_server/main/CMakeLists.txt +++ b/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/main/CMakeLists.txt @@ -1,3 +1,26 @@ +# [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 # @@ -74,7 +97,7 @@ endif() ## register_component() idf_component_register( - SRCS main.c server.c time_helper.c wifi_connect.c + SRCS main.c echoserver.c time_helper.c wifi_connect.c INCLUDE_DIRS "." "./include") # 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_server/main/server.h b/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/main/include/echoserver.h similarity index 69% rename from ide/Espressif/ESP-IDF/examples/wolfssh_server/main/server.h rename to ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/main/include/echoserver.h index 67a9dabb8..ac7e17cf2 100644 --- a/ide/Espressif/ESP-IDF/examples/wolfssh_server/main/server.h +++ b/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/main/include/echoserver.h @@ -1,4 +1,4 @@ -/* server.h +/* echoserver.h * * Copyright (C) 2014-2023 wolfSSL Inc. * @@ -19,12 +19,17 @@ */ -#ifndef _WOLFSSH_EXAMPLES_SERVER_H_ -#define _WOLFSSH_EXAMPLES_SERVER_H_ +#ifndef _WOLFSSH_EXAMPLES_ECHOSERVER_H_ +#define _WOLFSSH_EXAMPLES_ECHOSERVER_H_ -#include +#include -THREAD_RETURN WOLFSSH_THREAD server_test(void* args); +#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_SERVER_H_ */ + +#endif /* _WOLFSSH_EXAMPLES_ECHOSERVER_H_ */ diff --git a/ide/Espressif/ESP-IDF/examples/wolfssh_server/main/include/main.h b/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/main/include/main.h similarity index 100% rename from ide/Espressif/ESP-IDF/examples/wolfssh_server/main/include/main.h rename to ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/main/include/main.h diff --git a/ide/Espressif/ESP-IDF/examples/wolfssh_server/main/include/time_helper.h b/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/main/include/time_helper.h similarity index 100% rename from ide/Espressif/ESP-IDF/examples/wolfssh_server/main/include/time_helper.h rename to ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/main/include/time_helper.h diff --git a/ide/Espressif/ESP-IDF/examples/wolfssh_server/main/include/wifi_connect.h b/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/main/include/wifi_connect.h similarity index 100% rename from ide/Espressif/ESP-IDF/examples/wolfssh_server/main/include/wifi_connect.h rename to ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/main/include/wifi_connect.h diff --git a/ide/Espressif/ESP-IDF/examples/wolfssh_server/main/main.c b/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/main/main.c similarity index 98% rename from ide/Espressif/ESP-IDF/examples/wolfssh_server/main/main.c rename to ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/main/main.c index 25b0d6759..7781f4281 100644 --- a/ide/Espressif/ESP-IDF/examples/wolfssh_server/main/main.c +++ b/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/main/main.c @@ -20,7 +20,8 @@ */ #include "sdkconfig.h" #include "main.h" -#include "server.h" +#include "echoserver.h" + /* ESP specific */ #include #include @@ -39,13 +40,11 @@ #include "time_helper.h" static const char* const TAG = "My Project"; -int myoptind = 0; -char* myoptarg = NULL; void app_main(void) { - func_args args = {0}; + void* args = {0}; int ret = ESP_OK; ESP_LOGI(TAG, "------------ wolfSSL wolfSSH template Example ----------"); @@ -159,7 +158,7 @@ void app_main(void) /* 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 */ - server_test(&args); + echoserver_test(&args); ESP_LOGI(TAG, "\n\nDone!" "If running from idf.py monitor, press twice: Ctrl+]"); diff --git a/ide/Espressif/ESP-IDF/examples/wolfssh_server/main/time_helper.c b/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/main/time_helper.c similarity index 99% rename from ide/Espressif/ESP-IDF/examples/wolfssh_server/main/time_helper.c rename to ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/main/time_helper.c index 896dbf04c..0abf70c5a 100644 --- a/ide/Espressif/ESP-IDF/examples/wolfssh_server/main/time_helper.c +++ b/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/main/time_helper.c @@ -248,17 +248,13 @@ int set_time(void) ESP_LOGI(TAG, "Setting the time. Startup time:"); esp_show_current_datetime(); -// ESP_LOGI(TAG, "return."); -// return ESP_OK; /* TODO */ #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_LOGI(TAG, "esp_show_current_datetime."); esp_show_current_datetime(); - ret = -4; #else /* otherwise set a fixed time that was hard coded */ diff --git a/ide/Espressif/ESP-IDF/examples/wolfssh_server/main/wifi_connect.c b/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/main/wifi_connect.c similarity index 100% rename from ide/Espressif/ESP-IDF/examples/wolfssh_server/main/wifi_connect.c rename to ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/main/wifi_connect.c diff --git a/ide/Espressif/ESP-IDF/examples/wolfssh_server/partitions_singleapp_large.csv b/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/partitions_singleapp_large.csv similarity index 100% rename from ide/Espressif/ESP-IDF/examples/wolfssh_server/partitions_singleapp_large.csv rename to ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/partitions_singleapp_large.csv diff --git a/ide/Espressif/ESP-IDF/examples/wolfssh_server/sdkconfig.defaults b/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/sdkconfig.defaults similarity index 100% rename from ide/Espressif/ESP-IDF/examples/wolfssh_server/sdkconfig.defaults rename to ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/sdkconfig.defaults diff --git a/ide/Espressif/ESP-IDF/examples/wolfssh_server/components/wolfssl/include/user_settings.h b/ide/Espressif/ESP-IDF/examples/wolfssh_server/components/wolfssl/include/user_settings.h deleted file mode 100644 index 43dc5bad9..000000000 --- a/ide/Espressif/ESP-IDF/examples/wolfssh_server/components/wolfssl/include/user_settings.h +++ /dev/null @@ -1,283 +0,0 @@ -/* 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 */ -#define ESP_ENABLE_WOLFSSH -#ifdef ESP_ENABLE_WOLFSSH - /* 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 */ - -#define BENCH_EMBEDDED -#define USE_CERT_BUFFERS_2048 - -/* TLS 1.3 */ -// #define WOLFSSL_TLS13 -// #define HAVE_TLS_EXTENSIONS -// #define WC_RSA_PSS -#define HAVE_HKDF -#define HAVE_AEAD -// #define HAVE_SUPPORTED_CURVES - -#ifdef HAVE_TLS_EXTENSIONS -#endif -#define WOLFSSL_BENCHMARK_FIXED_UNITS_KB - - -#define NO_FILESYSTEM - -#define HAVE_AESGCM - -#define WOLFSSL_RIPEMD -/* when you want to use SHA224 */ -/* #define WOLFSSL_SHA224 */ - -#define NO_OLD_TLS - -/* when you want to use SHA384 */ -/* #define WOLFSSL_SHA384 */ - -/* #define WOLFSSL_SHA3 */ - -#define WOLFSSL_SHA512 -#define HAVE_ECC -#define HAVE_CURVE25519 -#define CURVE25519_SMALL -#define HAVE_ED25519 - -/* 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 */ - -/* 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 - -/* rsa primitive specific definition */ -#if defined(WOLFSSL_ESP32) || defined(WOLFSSL_ESPWROOM32SE) - /* 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 */ - #define ESP_RSA_MULM_BITS 9 -#endif - -// #define RSA_LOW_MEM -#define WOLFSSH_NO_RSA -/* The default SSH Windows size is massive for an embedded target. Limit it: */ -#define DEFAULT_WINDOW_SZ 2000 - -/* 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 - -#define HASH_SIZE_LIMIT /* for test.c */ - -#define USE_FAST_MATH - -/* optionally use SP_MATH */ -/* #define SP_MATH */ - -#define WOLFSSL_SMALL_STACK - -#define HAVE_VERSION_EXTENDED_INFO -#define HAVE_WC_INTROSPECTION - -/* allows for all version info, even that suppressed with introspection */ -#define ALLOW_BINARY_MISMATCH_INTROSPECTION - -/* 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 - -/* Default is HW enabled unless turned off. -** Uncomment these lines for SW: */ -#if defined(CONFIG_IDF_TARGET_ESP32) - /* #define NO_ESP32_CRYPT */ - /* #define NO_WOLFSSL_ESP32_CRYPT_HASH */ - /* #define NO_WOLFSSL_ESP32_CRYPT_AES */ - /* #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI */ -#elif defined(CONFIG_IDF_TARGET_ESP32S2) - #define NO_ESP32_CRYPT - #define NO_WOLFSSL_ESP32_CRYPT_HASH - #define NO_WOLFSSL_ESP32_CRYPT_AES - #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI -#elif defined(CONFIG_IDF_TARGET_ESP32S3) - /* #define NO_ESP32_CRYPT */ - /* #define NO_WOLFSSL_ESP32_CRYPT_HASH */ - /* #define NO_WOLFSSL_ESP32_CRYPT_AES */ - /* #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI */ -#elif defined(CONFIG_IDF_TARGET_ESP32C2) - #define NO_ESP32_CRYPT - #define NO_WOLFSSL_ESP32_CRYPT_HASH - #define NO_WOLFSSL_ESP32_CRYPT_AES - #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI -#elif defined(CONFIG_IDF_TARGET_ESP32C3) - #define NO_ESP32_CRYPT - #define NO_WOLFSSL_ESP32_CRYPT_HASH - #define NO_WOLFSSL_ESP32_CRYPT_AES - #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI -#elif defined(CONFIG_IDF_TARGET_ESP32C6) - #define NO_ESP32_CRYPT - #define NO_WOLFSSL_ESP32_CRYPT_HASH - #define NO_WOLFSSL_ESP32_CRYPT_AES - #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI -#elif defined(CONFIG_IDF_TARGET_ESP32H2) - #define NO_ESP32_CRYPT - #define NO_WOLFSSL_ESP32_CRYPT_HASH - #define NO_WOLFSSL_ESP32_CRYPT_AES - #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI -#else - #define NO_ESP32_CRYPT - #define NO_WOLFSSL_ESP32_CRYPT_HASH - #define NO_WOLFSSL_ESP32_CRYPT_AES - #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI -#endif diff --git a/ide/Espressif/ESP-IDF/examples/wolfssh_server/main/server.c b/ide/Espressif/ESP-IDF/examples/wolfssh_server/main/server.c deleted file mode 100644 index 4d08fc8b5..000000000 --- a/ide/Espressif/ESP-IDF/examples/wolfssh_server/main/server.c +++ /dev/null @@ -1,825 +0,0 @@ -/* server.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_THREADING - - -#ifdef WOLFSSL_USER_SETTINGS - #include -#else - #include -#endif - -#include -#include -#include -#include -#include -#include -#include "server.h" - -#ifdef NO_FILESYSTEM - #include - #ifdef WOLFSSH_SCP - #include - #endif -#endif - - -#ifndef NO_WOLFSSH_SERVER - -static const char serverBanner[] = "wolfSSH Example Server\n"; - - -typedef struct { - WOLFSSH* ssh; - SOCKET_T fd; - word32 id; - char nonBlock; -} thread_ctx_t; - - -#ifndef EXAMPLE_HIGHWATER_MARK - #define EXAMPLE_HIGHWATER_MARK 0x3FFF8000 /* 1GB - 32kB */ -#endif -#ifndef EXAMPLE_BUFFER_SZ - #define EXAMPLE_BUFFER_SZ 4096 -#endif -#define SCRATCH_BUFFER_SZ 1200 - - -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) -{ - char stats[1024]; - word32 statsSz; - word32 txCount, rxCount, seq, peerSeq; - - wolfSSH_GetStats(ctx->ssh, &txCount, &rxCount, &seq, &peerSeq); - - WSNPRINTF(stats, sizeof(stats), - "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)strlen(stats); - - fprintf(stderr, "%s", stats); - return wolfSSH_stream_send(ctx->ssh, (byte*)stats, statsSz); -} - - -static int NonBlockSSH_accept(WOLFSSH* ssh) -{ - int ret; - int error; - SOCKET_T sockfd; - int select_ret = 0; - - ret = wolfSSH_accept(ssh); - error = wolfSSH_get_error(ssh); - sockfd = (SOCKET_T)wolfSSH_get_fd(ssh); - - while (ret != WS_SUCCESS && - (error == WS_WANT_READ || error == WS_WANT_WRITE)) - { - if (error == WS_WANT_READ) - printf("... client would read block\n"); - else if (error == WS_WANT_WRITE) - printf("... client 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; - thread_ctx_t* threadCtx = (thread_ctx_t*)vArgs; - -#if defined(WOLFSSH_SCP) && defined(NO_FILESYSTEM) - ScpBuffer scpBufferRecv, scpBufferSend; - byte fileBuffer[49000]; - byte fileTmp[] = "wolfSSH SCP buffer file"; - - WMEMSET(&scpBufferRecv, 0, sizeof(ScpBuffer)); - scpBufferRecv.buffer = fileBuffer; - scpBufferRecv.bufferSz = sizeof(fileBuffer); - wolfSSH_SetScpRecvCtx(threadCtx->ssh, (void*)&scpBufferRecv); - - /* make buffer file to send if asked */ - WMEMSET(&scpBufferSend, 0, sizeof(ScpBuffer)); - WMEMCPY(scpBufferSend.name, "test.txt", sizeof("test.txt")); - scpBufferSend.nameSz = WSTRLEN("test.txt"); - scpBufferSend.buffer = fileTmp; - scpBufferSend.bufferSz = sizeof(fileBuffer); - scpBufferSend.fileSz = sizeof(fileTmp); - scpBufferSend.mode = 0x1A4; - wolfSSH_SetScpSendCtx(threadCtx->ssh, (void*)&scpBufferSend); -#endif - - if (!threadCtx->nonBlock) - ret = wolfSSH_accept(threadCtx->ssh); - else - ret = NonBlockSSH_accept(threadCtx->ssh); - - if (ret == WS_SUCCESS) { - byte* buf = NULL; - byte* tmpBuf; - int bufSz, backlogSz = 0, rxSz, txSz, stop = 0, txSum; - - do { - bufSz = EXAMPLE_BUFFER_SZ + backlogSz; - - tmpBuf = (byte*)realloc(buf, bufSz); - if (tmpBuf == NULL) - stop = 1; - else - buf = tmpBuf; - - if (!stop) { - do { - rxSz = wolfSSH_stream_read(threadCtx->ssh, - buf + backlogSz, - EXAMPLE_BUFFER_SZ); - if (rxSz <= 0) - rxSz = wolfSSH_get_error(threadCtx->ssh); - } while (rxSz == WS_WANT_READ || rxSz == WS_WANT_WRITE); - - if (rxSz > 0) { - backlogSz += rxSz; - txSum = 0; - txSz = 0; - - while (backlogSz != txSum && txSz >= 0 && !stop) { - txSz = wolfSSH_stream_send(threadCtx->ssh, - buf + txSum, - backlogSz - txSum); - - if (txSz > 0) { - byte c; - const byte matches[] = { 0x03, 0x05, 0x06, 0x00 }; - - c = find_char(matches, buf + txSum, txSz); - switch (c) { - case 0x03: - stop = 1; - break; - case 0x06: - if (wolfSSH_TriggerKeyExchange(threadCtx->ssh) - != WS_SUCCESS) - stop = 1; - break; - case 0x05: - if (dump_stats(threadCtx) <= 0) - stop = 1; - break; - } - txSum += txSz; - } - else if (txSz != WS_REKEYING) - stop = 1; - } - - if (txSum < backlogSz) - memmove(buf, buf + txSum, backlogSz - txSum); - backlogSz -= txSum; - } - else - stop = 1; - } - } while (!stop); - - free(buf); - } else if (ret == WS_SCP_COMPLETE) { - printf("scp file transfer completed\n"); - #if defined(WOLFSSH_SCP) && defined(NO_FILESYSTEM) - if (scpBufferRecv.fileSz > 0) { - word32 z; - - printf("file name : %s\n", scpBufferRecv.name); - printf(" size : %d\n", scpBufferRecv.fileSz); - printf(" mode : %o\n", scpBufferRecv.mode); - printf(" mTime : %lu\n", scpBufferRecv.mTime); - printf("\n"); - - for (z = 0; z < scpBufferRecv.fileSz; z++) - printf("%c", scpBufferRecv.buffer[z]); - printf("\n"); - } - #endif - } else if (ret == WS_SFTP_COMPLETE) { - printf("Use example/echoserver/echoserver for SFTP\n"); - } - wolfSSH_stream_exit(threadCtx->ssh, 0); - WCLOSESOCKET(threadCtx->fd); - wolfSSH_free(threadCtx->ssh); - free(threadCtx); - - return 0; -} - -#ifndef NO_FILESYSTEM -static int load_file(const char* fileName, byte* buf, word32 bufSz) -{ - FILE* file; - word32 fileSz; - word32 readSz; - - if (fileName == NULL) return 0; - - if (WFOPEN(NULL, &file, fileName, "rb") != 0) - return 0; - fseek(file, 0, SEEK_END); - fileSz = (word32)ftell(file); - rewind(file); - - if (fileSz > bufSz) { - fclose(file); - return 0; - } - - readSz = (word32)fread(buf, 1, fileSz, file); - if (readSz < fileSz) { - fclose(file); - return 0; - } - - fclose(file); - - return fileSz; -} -#endif /* !NO_FILESYSTEM */ - -/* 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 ? "./keys/server-key-ecc.der" : - "./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, rsa_key_der_2048, sizeof_rsa_key_der_2048); - sz = sizeof_rsa_key_der_2048; - } -#endif - - return sz; -} - - -static INLINE void c32toa(word32 u32, byte* c) -{ - c[0] = (u32 >> 24) & 0xff; - c[1] = (u32 >> 16) & 0xff; - c[2] = (u32 >> 8) & 0xff; - c[3] = u32 & 0xff; -} - - -/* 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*)malloc(sizeof(PwMap)); - if (map != NULL) { - wc_Sha256 sha; - byte flatSz[4]; - - map->type = type; - if (usernameSz >= sizeof(map->username)) - usernameSz = sizeof(map->username) - 1; - memcpy(map->username, username, usernameSz + 1); - map->username[usernameSz] = 0; - map->usernameSz = usernameSz; - - wc_InitSha256(&sha); - c32toa(pSz, flatSz); - wc_Sha256Update(&sha, flatSz, sizeof(flatSz)); - wc_Sha256Update(&sha, p, pSz); - wc_Sha256Final(&sha, 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; - memset(cur, 0, sizeof(PwMap)); - free(cur); - } - } -} - - -static const char samplePasswordBuffer[] = - "jill:upthehill\n" - "jack:fetchapail\n"; - - -static const char samplePublicKeyEccBuffer[] = - "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAA" - "BBBNkI5JTP6D0lF42tbxX19cE87hztUS6FSDoGvPfiU0CgeNSbI+aFdKIzTP5CQEJSvm25" - "qUzgDtH7oyaQROUnNvk= hansel\n" - "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAA" - "BBBKAtH8cqaDbtJFjtviLobHBmjCtG56DMkP6A4M2H9zX2/YCg1h9bYS7WHd9UQDwXO1Hh" - "IZzRYecXh7SG9P4GhRY= gretel\n"; - - -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"; - - -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 = strchr(str, ':'); - if (delimiter == NULL) { - return -1; - } - username = str; - *delimiter = 0; - password = delimiter + 1; - str = strchr(password, '\n'); - if (str == NULL) { - return -1; - } - *str = 0; - str++; - if (PwMapNew(list, WOLFSSH_USERAUTH_PASSWORD, - (byte*)username, (word32)strlen(username), - (byte*)password, (word32)strlen(password)) == NULL ) { - - return -1; - } - } - - return 0; -} - - -static int LoadPublicKeyBuffer(byte* buf, word32 bufSz, PwMapList* list) -{ - char* str = (char*)buf; - char* delimiter; - byte* publicKey64; - word32 publicKey64Sz; - byte* username; - word32 usernameSz; - byte publicKey[300]; - 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 != 0) { - /* Skip the public key type. This example will always be ssh-rsa. */ - delimiter = strchr(str, ' '); - if (delimiter == NULL) { - return -1; - } - str = delimiter + 1; - delimiter = strchr(str, ' '); - if (delimiter == NULL) { - return -1; - } - publicKey64 = (byte*)str; - *delimiter = 0; - publicKey64Sz = (word32)(delimiter - str); - str = delimiter + 1; - delimiter = strchr(str, '\n'); - if (delimiter == NULL) { - return -1; - } - username = (byte*)str; - *delimiter = 0; - usernameSz = (word32)(delimiter - str); - str = delimiter + 1; - publicKeySz = sizeof(publicKey); - - if (Base64_Decode(publicKey64, publicKey64Sz, - publicKey, &publicKeySz) != 0) { - - return -1; - } - - if (PwMapNew(list, WOLFSSH_USERAUTH_PUBLICKEY, - username, usernameSz, - publicKey, publicKeySz) == NULL ) { - - return -1; - } - } - - return 0; -} - - -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 && - authType != WOLFSSH_USERAUTH_PUBLICKEY) { - - return WOLFSSH_USERAUTH_FAILURE; - } - - /* Hash the password or public key with its length. */ - { - wc_Sha256 sha; - byte flatSz[4]; - wc_InitSha256(&sha); - if (authType == WOLFSSH_USERAUTH_PASSWORD) { - c32toa(authData->sf.password.passwordSz, flatSz); - wc_Sha256Update(&sha, flatSz, sizeof(flatSz)); - wc_Sha256Update(&sha, - authData->sf.password.password, - authData->sf.password.passwordSz); - } - else if (authType == WOLFSSH_USERAUTH_PUBLICKEY) { - c32toa(authData->sf.publicKey.publicKeySz, flatSz); - wc_Sha256Update(&sha, flatSz, sizeof(flatSz)); - wc_Sha256Update(&sha, - authData->sf.publicKey.publicKey, - authData->sf.publicKey.publicKeySz); - } - wc_Sha256Final(&sha, authHash); - } - - list = (PwMapList*)ctx; - map = list->head; - - while (map != NULL) { - if (authData->usernameSz == map->usernameSz && - memcmp(authData->username, map->username, map->usernameSz) == 0) { - - if (authData->type == map->type) { - if (memcmp(map->p, authHash, WC_SHA256_DIGEST_SIZE) == 0) { - return WOLFSSH_USERAUTH_SUCCESS; - } - else { - return (authType == WOLFSSH_USERAUTH_PASSWORD ? - WOLFSSH_USERAUTH_INVALID_PASSWORD : - WOLFSSH_USERAUTH_INVALID_PUBLICKEY); - } - } - else { - return WOLFSSH_USERAUTH_INVALID_AUTHTYPE; - } - } - map = map->next; - } - - return WOLFSSH_USERAUTH_INVALID_USER; -} - - -static void ShowUsage(void) -{ - printf("server %s\n", LIBWOLFSSH_VERSION_STRING); - printf(" -h display this help and exit\n"); - printf(" -m allow multiple connections\n"); - printf(" -e use ECC private key\n"); - printf(" -N use non-blocking sockets\n"); -} - - -THREAD_RETURN WOLFSSH_THREAD server_test(void* args) -{ - WOLFSSH_CTX* ctx = NULL; - PwMapList pwMapList; - SOCKET_T listenFd = 0; - word32 defaultHighwater = EXAMPLE_HIGHWATER_MARK; - word32 threadCount = 0; - word16 port = wolfSshPort; - char multipleConnections = 0; - char useEcc = 0; - int ch; - char nonBlock = 0; - - int argc = ((func_args*)args)->argc; - char** argv = ((func_args*)args)->argv; - ((func_args*)args)->return_code = 0; - - while ((ch = mygetopt(argc, argv, "hmeN")) != -1) { - switch (ch) { - case 'h' : - ShowUsage(); - exit(EXIT_SUCCESS); - - case 'm' : - multipleConnections = 1; - break; - - case 'e' : - useEcc = 1; - break; - - case 'N' : - nonBlock = 1; - break; - - default: - ShowUsage(); - exit(MY_EX_USAGE); - } - } - -#ifndef NO_MAIN_DRIVER - myoptind = 0; /* reset for test cases */ -#endif - -#ifdef WOLFSSH_NO_RSA - /* If wolfCrypt isn't built with RSA, force ECC on. */ - useEcc = 1; -#endif - - if (wolfSSH_Init() != WS_SUCCESS) { - fprintf(stderr, "Couldn't initialize wolfSSH.\n"); - exit(EXIT_FAILURE); - } - - ctx = wolfSSH_CTX_new(WOLFSSH_ENDPOINT_SERVER, NULL); - if (ctx == NULL) { - fprintf(stderr, "Couldn't allocate SSH CTX data.\n"); - exit(EXIT_FAILURE); - } - - memset(&pwMapList, 0, sizeof(pwMapList)); - wolfSSH_SetUserAuth(ctx, wsUserAuth); - wolfSSH_CTX_SetBanner(ctx, serverBanner); - - { - const char* bufName; - byte buf[SCRATCH_BUFFER_SZ]; - word32 bufSz; - - bufSz = load_key(useEcc, buf, SCRATCH_BUFFER_SZ); - if (bufSz == 0) { - fprintf(stderr, "Couldn't load key.\n"); - exit(EXIT_FAILURE); - } - if (wolfSSH_CTX_UsePrivateKey_buffer(ctx, buf, bufSz, - WOLFSSH_FORMAT_ASN1) < 0) { - fprintf(stderr, "Couldn't use key buffer.\n"); - exit(EXIT_FAILURE); - } - - bufSz = (word32)strlen(samplePasswordBuffer); - memcpy(buf, samplePasswordBuffer, bufSz); - buf[bufSz] = 0; - LoadPasswordBuffer(buf, bufSz, &pwMapList); - - bufName = useEcc ? samplePublicKeyEccBuffer : - samplePublicKeyRsaBuffer; - bufSz = (word32)strlen(bufName); - memcpy(buf, bufName, bufSz); - buf[bufSz] = 0; - LoadPublicKeyBuffer(buf, bufSz, &pwMapList); - } - - tcp_listen(&listenFd, &port, 1); - - do { - SOCKET_T clientFd = 0; - SOCKADDR_IN_T clientAddr; - socklen_t clientAddrSz = sizeof(clientAddr); -#ifndef SINGLE_THREADED - THREAD_TYPE thread; -#endif - WOLFSSH* ssh; - thread_ctx_t* threadCtx; - - threadCtx = (thread_ctx_t*)malloc(sizeof(thread_ctx_t)); - if (threadCtx == NULL) { - fprintf(stderr, "Couldn't allocate thread context data.\n"); - exit(EXIT_FAILURE); - } - - ssh = wolfSSH_new(ctx); - if (ssh == NULL) { - fprintf(stderr, "Couldn't allocate SSH data.\n"); - exit(EXIT_FAILURE); - } - 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); - } - - clientFd = accept(listenFd, (struct sockaddr*)&clientAddr, - &clientAddrSz); - if (clientFd == -1) - err_sys("tcp accept failed"); - - if (nonBlock) - tcp_set_nonblocking(&clientFd); - - wolfSSH_set_fd(ssh, (int)clientFd); - - threadCtx->ssh = ssh; - threadCtx->fd = clientFd; - threadCtx->id = threadCount++; - threadCtx->nonBlock = nonBlock; - -#ifndef SINGLE_THREADED -#if defined(WOLFSSH_OLD_THREADING) || defined(WOLFSSL_THREAD_NO_JOIN) - if (multipleConnections) - ThreadStartNoJoin(server_worker, threadCtx); - else -#endif - { - ThreadStart(server_worker, threadCtx, &thread); - ThreadJoin(thread); - } -#else - server_worker(threadCtx); -#endif /* SINGLE_THREADED */ - } while (multipleConnections); - - PwMapListDelete(&pwMapList); - wolfSSH_CTX_free(ctx); - if (wolfSSH_Cleanup() != WS_SUCCESS) { - fprintf(stderr, "Couldn't clean up wolfSSH.\n"); - exit(EXIT_FAILURE); - } -#if !defined(WOLFSSH_NO_ECC) && defined(FP_ECC) && defined(HAVE_THREAD_LS) - wc_ecc_fp_free(); /* free per thread cache */ -#endif - - WOLFSSL_RETURN_FROM_THREAD(0); -} - -#endif /* NO_WOLFSSH_SERVER */ - -#ifndef NO_MAIN_DRIVER - - int main(int argc, char** argv) - { - func_args args; - - args.argc = argc; - args.argv = argv; - args.return_code = 0; - - WSTARTTCP(); - - ChangeToWolfSshRoot(); - #ifdef DEBUG_WOLFSSH - wolfSSH_Debugging_ON(); - #endif - - wolfSSH_Init(); - -#ifndef NO_WOLFSSH_SERVER - server_test(&args); -#else - printf("wolfSSH compiled without server support\n"); -#endif - - wolfSSH_Cleanup(); - - return args.return_code; - } - -#endif /* NO_MAIN_DRIVER */