diff --git a/.github/workflows/zephyr.yml b/.github/workflows/zephyr.yml new file mode 100644 index 000000000..40649231d --- /dev/null +++ b/.github/workflows/zephyr.yml @@ -0,0 +1,92 @@ +name: Zephyr tests + +on: + push: + branches: [ '*' ] + pull_request: + branches: [ '*' ] + +jobs: + run_test: + name: Build and run + strategy: + matrix: + config: + - zephyr-ref: v3.4.0 + zephyr-sdk: 0.16.1 + runs-on: ubuntu-latest + # This should be a safe limit for the tests to run. + timeout-minutes: 15 + steps: + - name: Install dependencies + run: | + # Don't prompt for anything + export DEBIAN_FRONTEND=noninteractive + sudo apt-get update + # most of the ci-base zephyr docker image packages + sudo apt-get install -y zip bridge-utils uml-utilities \ + git cmake ninja-build gperf ccache dfu-util device-tree-compiler wget \ + python3-dev python3-pip python3-setuptools python3-tk python3-wheel xz-utils file \ + make gcc gcc-multilib g++-multilib libsdl2-dev libmagic1 \ + autoconf automake bison build-essential ca-certificates cargo ccache chrpath cmake \ + cpio device-tree-compiler dfu-util diffstat dos2unix doxygen file flex g++ gawk gcc \ + gcovr git git-core gnupg gperf gtk-sharp2 help2man iproute2 lcov libcairo2-dev \ + libglib2.0-dev libgtk2.0-0 liblocale-gettext-perl libncurses5-dev libpcap-dev \ + libpopt0 libsdl1.2-dev libsdl2-dev libssl-dev libtool libtool-bin locales make \ + net-tools ninja-build openssh-client parallel pkg-config python3-dev python3-pip \ + python3-ply python3-setuptools python-is-python3 qemu rsync socat srecord sudo \ + texinfo unzip wget ovmf xz-utils + + - name: Install west + run: sudo pip install west + + - name: Init west workspace + run: west init --mr ${{ matrix.config.zephyr-ref }} zephyr + + - name: Update west.yml + working-directory: zephyr/zephyr + run: | + REF=$(echo '${{ github.ref }}' | sed -e 's/\//\\\//g') + sed -e 's/remotes:/remotes:\n \- name: wolfssl\n url\-base: https:\/\/github.com\/wolfssl/' -i west.yml + sed -e "s/remotes:/remotes:\n \- name: wolfssh\n url\-base: https:\/\/github.com\/${{ github.repository_owner }}/" -i west.yml + sed -e "s/projects:/projects:\n \- name: wolfssh\n path: modules\/lib\/wolfssh\n remote: wolfssh\n revision: $REF/" -i west.yml + sed -e 's/projects:/projects:\n \- name: wolfssl\n path: modules\/crypto\/wolfssl\n remote: wolfssl\n revision: master/' -i west.yml + + - name: Update west workspace + working-directory: zephyr + run: west update -n -o=--depth=1 + + - name: Export zephyr + working-directory: zephyr + run: west zephyr-export + + - name: Install pip dependencies + working-directory: zephyr + run: sudo pip install -r zephyr/scripts/requirements.txt + + - name: Install zephyr SDK + run: | + wget -q https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v${{ matrix.config.zephyr-sdk }}/zephyr-sdk-${{ matrix.config.zephyr-sdk }}_linux-x86_64.tar.xz + tar xf zephyr-sdk-${{ matrix.config.zephyr-sdk }}_linux-x86_64.tar.xz + cd zephyr-sdk-${{ matrix.config.zephyr-sdk }} + ./setup.sh -h -c + + - name: Run wolfssh tests + id: wolfssh-test + working-directory: zephyr + run: | + ./zephyr/scripts/twister --testsuite-root modules/lib/wolfssh --test zephyr/samples/tests/sample.lib.wolfssh_tests -vvv + rm -rf zephyr/twister-out + + - name: Zip failure logs + if: ${{ failure() && steps.wolfssh-test.outcome == 'failure' }} + run: | + zip -9 -r logs.zip zephyr/twister-out + + - name: Upload failure logs + if: ${{ failure() && steps.wolfssh-test.outcome == 'failure' }} + uses: actions/upload-artifact@v3 + with: + name: zephyr-client-test-logs + path: logs.zip + retention-days: 5 diff --git a/.gitignore b/.gitignore index 46dea9e79..c37eb63f4 100644 --- a/.gitignore +++ b/.gitignore @@ -83,3 +83,8 @@ Debug Release DLL Debug DLL Release + +# Eclipse +.cproject +.project +.settings diff --git a/examples/client/client.c b/examples/client/client.c index 5d4439f09..b1f523881 100644 --- a/examples/client/client.c +++ b/examples/client/client.c @@ -39,7 +39,8 @@ #include #include "examples/client/client.h" #include "examples/client/common.h" -#if !defined(USE_WINDOWS_API) && !defined(MICROCHIP_PIC32) +#if !defined(USE_WINDOWS_API) && !defined(MICROCHIP_PIC32) && \ + defined(WOLFSSH_TERM) && !defined(NO_FILESYSTEM) #include #endif @@ -124,15 +125,6 @@ static const char* certName = NULL; static const char* caCert = NULL; -#if defined(WOLFSSH_AGENT) -static inline void ato32(const byte* c, word32* u32) -{ - *u32 = (c[0] << 24) | (c[1] << 16) | (c[2] << 8) | c[3]; -} -#endif - - - static int NonBlockSSH_connect(WOLFSSH* ssh) { int ret; @@ -174,7 +166,8 @@ static int NonBlockSSH_connect(WOLFSSH* ssh) return ret; } -#if !defined(SINGLE_THREADED) && !defined(WOLFSSL_NUCLEUS) +#if !defined(SINGLE_THREADED) && !defined(WOLFSSL_NUCLEUS) && \ + defined(WOLFSSH_TERM) && !defined(NO_FILESYSTEM) typedef struct thread_args { WOLFSSH* ssh; @@ -345,6 +338,12 @@ static THREAD_RET readInput(void* in) return THREAD_RET_SUCCESS; } +#if defined(WOLFSSH_AGENT) +static inline void ato32(const byte* c, word32* u32) +{ + *u32 = (c[0] << 24) | (c[1] << 16) | (c[2] << 8) | c[3]; +} +#endif static THREAD_RET readPeer(void* in) { @@ -460,13 +459,13 @@ static THREAD_RET readPeer(void* in) } else { printf("%s", buf); - fflush(stdout); + WFFLUSH(stdout); } #else if (write(STDOUT_FILENO, buf, ret) < 0) { perror("write to stdout error "); } - fflush(stdout); + WFFLUSH(stdout); #endif } if (wolfSSH_stream_peek(args->ssh, buf, bufSz) <= 0) { @@ -640,6 +639,8 @@ THREAD_RETURN WOLFSSH_THREAD client_test(void* args) char** argv = ((func_args*)args)->argv; ((func_args*)args)->return_code = 0; + (void)keepOpen; + while ((ch = mygetopt(argc, argv, "?ac:h:i:j:p:tu:xzNP:RJ:A:Xe")) != -1) { switch (ch) { case 'h': @@ -859,7 +860,8 @@ THREAD_RETURN WOLFSSH_THREAD client_test(void* args) if (ret != WS_SUCCESS) err_sys("Couldn't connect SSH stream."); -#if !defined(SINGLE_THREADED) && !defined(WOLFSSL_NUCLEUS) +#if !defined(SINGLE_THREADED) && !defined(WOLFSSL_NUCLEUS) && \ + defined(WOLFSSH_TERM) && !defined(NO_FILESYSTEM) if (keepOpen) /* set up for psuedo-terminal */ ClientSetEcho(2); @@ -995,7 +997,7 @@ THREAD_RETURN WOLFSSH_THREAD client_test(void* args) wc_ecc_fp_free(); /* free per thread cache */ #endif - return 0; + WOLFSSL_RETURN_FROM_THREAD(0); } #endif /* NO_WOLFSSH_CLIENT */ diff --git a/examples/client/common.c b/examples/client/common.c index 9578410b2..671532a4d 100644 --- a/examples/client/common.c +++ b/examples/client/common.c @@ -25,14 +25,17 @@ #define WOLFSSH_TEST_CLIENT +#include #include #include #include #include #include +#include #include #include "examples/client/common.h" -#ifndef USE_WINDOWS_API +#if !defined(USE_WINDOWS_API) && !defined(MICROCHIP_PIC32) && \ + !defined(WOLFSSH_ZEPHYR) #include #endif @@ -487,11 +490,13 @@ int ClientUserAuth(byte authType, passwordSz = (word32)strlen(defaultPassword); memcpy(userPassword, defaultPassword, passwordSz); } +#ifdef WOLFSSH_TERM else { printf("Password: "); - fflush(stdout); + WFFLUSH(stdout); ClientSetEcho(0); - if (fgets((char*)userPassword, sizeof(userPassword), stdin) == NULL) { + if (WFGETS((char*)userPassword, sizeof(userPassword), stdin) + == NULL) { fprintf(stderr, "Getting password failed.\n"); ret = WOLFSSH_USERAUTH_FAILURE; } @@ -505,8 +510,9 @@ int ClientUserAuth(byte authType, #ifdef USE_WINDOWS_API printf("\r\n"); #endif - fflush(stdout); + WFFLUSH(stdout); } +#endif if (ret == WOLFSSH_USERAUTH_SUCCESS) { authData->sf.password.password = userPassword; @@ -518,6 +524,7 @@ int ClientUserAuth(byte authType, } +#ifdef WOLFSSH_TERM /* type = 2 : shell / execute command settings * type = 0 : password * type = 1 : restore default @@ -604,6 +611,7 @@ int ClientSetEcho(int type) return 0; } +#endif /* Set certificate to use and public key. @@ -662,7 +670,7 @@ int ClientSetPrivateKey(const char* privKeyName, int userEcc) &isPrivate, NULL); #else printf("file system not compiled in!\n"); - ret = WC_NOT_COMPILED; + ret = NOT_COMPILED_IN; #endif } diff --git a/examples/echoserver/echoserver.c b/examples/echoserver/echoserver.c index 0ac164c23..3d141bf4c 100644 --- a/examples/echoserver/echoserver.c +++ b/examples/echoserver/echoserver.c @@ -55,7 +55,7 @@ #undef WOLFSSH_SHELL #endif -#ifdef WOLFSSL_NUCLEUS +#if defined(WOLFSSL_NUCLEUS) || defined(WOLFSSH_ZEPHYR) /* use buffers for keys with server */ #define NO_FILESYSTEM #define WOLFSSH_NO_EXIT @@ -1153,7 +1153,7 @@ static int sftp_worker(thread_ctx_t* threadCtx) WOLFSSH* ssh = threadCtx->ssh; WS_SOCKET_T s; int ret = WS_SUCCESS; - int error; + int error = -1; int selected; unsigned char peek_buf[1]; int timeout = TEST_SFTP_TIMEOUT; @@ -1423,14 +1423,14 @@ static THREAD_RETURN WOLFSSH_THREAD server_worker(void* vArgs) WFREE(threadCtx, NULL, 0); - return 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) { - FILE* file; + WFILE* file; word32 fileSz; word32 readSz; @@ -1438,24 +1438,24 @@ static int load_file(const char* fileName, byte* buf, word32* bufSz) if (WFOPEN(NULL, &file, fileName, "rb") != 0) return 0; - fseek(file, 0, XSEEK_END); - fileSz = (word32)ftell(file); - rewind(file); + WFSEEK(NULL, file, 0, WSEEK_END); + fileSz = (word32)WFTELL(NULL, file); + WREWIND(NULL, file); if (fileSz > *bufSz) { if (buf == NULL) *bufSz = fileSz; - fclose(file); + WFCLOSE(NULL, file); return 0; } - readSz = (word32)fread(buf, 1, fileSz, file); + readSz = (word32)WFREAD(NULL, buf, 1, fileSz, file); if (readSz < fileSz) { - fclose(file); + WFCLOSE(NULL, file); return 0; } - fclose(file); + WFCLOSE(NULL, file); return fileSz; } @@ -1594,7 +1594,6 @@ static const char samplePasswordBuffer[] = "jack:fetchapail\n"; -#ifndef NO_FILESYSTEM #ifndef WOLFSSH_NO_ECC #ifndef WOLFSSH_NO_ECDSA_SHA2_NISTP256 static const char samplePublicKeyEccBuffer[] = @@ -1634,7 +1633,6 @@ static const char samplePublicKeyRsaBuffer[] = "biE57dK6BrH5iZwVLTQKux31uCJLPhiktI3iLbdlGZEctJkTasfVSsUizwVIyRjhVKmbdI" "RGwkU38D043AR1h0mUoGCPIKuqcFMf gretel\n"; #endif -#endif /* NO_FILESYSTEM */ #ifdef WOLFSSH_ALLOW_USERAUTH_NONE @@ -1834,7 +1832,7 @@ static int LoadPasswdList(StrList* strList, PwMapList* mapList) return count; } - +#ifndef NO_FILESYSTEM static int LoadPubKeyList(StrList* strList, int format, PwMapList* mapList) { char names[256]; @@ -1902,7 +1900,7 @@ static int LoadPubKeyList(StrList* strList, int format, PwMapList* mapList) return count; } - +#endif static int wsUserAuthResult(byte res, WS_UserAuthData* authData, @@ -2077,6 +2075,7 @@ static int SetDefaultSftpPath(WOLFSSH* ssh, const char* defaultSftpPath) 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; @@ -2086,6 +2085,11 @@ static int SetDefaultSftpPath(WOLFSSH* ssh, const char* defaultSftpPath) 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)) { @@ -2159,17 +2163,24 @@ static INLINE void SignalTcpReady(func_args* serverArgs, word16 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; - StrList* sshPubKeyList = NULL; - StrList* pemPubKeyList = NULL; - StrList* derPubKeyList = NULL; + #ifndef NO_FILESYSTEM + StrList* sshPubKeyList = NULL; + StrList* pemPubKeyList = NULL; + StrList* derPubKeyList = NULL; + #endif StrList* passwdList = NULL; - WS_SOCKET_T listenFd = 0; + WS_SOCKET_T listenFd = WOLFSSH_SOCKET_INVALID; word32 defaultHighwater = EXAMPLE_HIGHWATER_MARK; word32 threadCount = 0; int multipleConnections = 1; @@ -2181,7 +2192,9 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args) char* readyFile = NULL; const char* defaultSftpPath = NULL; char nonBlock = 0; - char* userPubKey = NULL; + #ifndef NO_FILESYSTEM + char* userPubKey = NULL; + #endif #ifdef WOLFSSH_CERTS char* caCert = NULL; #endif @@ -2198,7 +2211,7 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args) case '?' : ShowUsage(); serverArgs->return_code = MY_EX_USAGE; - return 0; + WOLFSSL_RETURN_FROM_THREAD(0); case '1': multipleConnections = 0; @@ -2225,17 +2238,13 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args) case 'p': if (myoptarg == NULL) { - err_sys("NULL port value"); - serverArgs->return_code = EXIT_FAILURE; - return 0; + ES_ERROR("NULL port value"); } else { port = (word16)atoi(myoptarg); #if !defined(NO_MAIN_DRIVER) || defined(USE_WINDOWS_API) if (port == 0) { - err_sys("port number cannot be 0"); - serverArgs->return_code = EXIT_FAILURE; - return 0; + ES_ERROR("port number cannot be 0"); } #endif } @@ -2253,6 +2262,7 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args) defaultSftpPath = myoptarg; break; +#ifndef NO_FILESYSTEM case 'j': userPubKey = myoptarg; break; @@ -2268,6 +2278,7 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args) case 'K': derPubKeyList = StrListAdd(derPubKeyList, myoptarg); break; +#endif case 'P': passwdList = StrListAdd(passwdList, myoptarg); @@ -2276,7 +2287,7 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args) default: ShowUsage(); serverArgs->return_code = MY_EX_USAGE; - return 0; + WOLFSSL_RETURN_FROM_THREAD(0); } } } @@ -2285,9 +2296,7 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args) #ifdef WOLFSSH_TEST_BLOCK if (!nonBlock) { - err_sys("Use -N when testing forced non blocking"); - serverArgs->return_code = EXIT_FAILURE; - return 0; + ES_ERROR("Use -N when testing forced non blocking"); } #endif @@ -2304,16 +2313,12 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args) (void)userEcc; if (wolfSSH_Init() != WS_SUCCESS) { - fprintf(stderr, "Couldn't initialize wolfSSH.\n"); - serverArgs->return_code = EXIT_FAILURE; - return 0; + ES_ERROR("Couldn't initialize wolfSSH.\n"); } ctx = wolfSSH_CTX_new(WOLFSSH_ENDPOINT_SERVER, NULL); if (ctx == NULL) { - fprintf(stderr, "Couldn't allocate SSH CTX data.\n"); - serverArgs->return_code = EXIT_FAILURE; - return 0; + ES_ERROR("Couldn't allocate SSH CTX data.\n"); } WMEMSET(&pwMapList, 0, sizeof(pwMapList)); @@ -2330,6 +2335,7 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args) wolfSSH_CTX_SetFwdCb(ctx, wolfSSH_FwdDefaultActions, NULL); #endif +#ifndef NO_FILESYSTEM if (sshPubKeyList) { LoadPubKeyList(sshPubKeyList, WOLFSSH_FORMAT_SSH, &pwMapList); StrListFree(sshPubKeyList); @@ -2345,6 +2351,7 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args) StrListFree(derPubKeyList); derPubKeyList = NULL; } +#endif if (passwdList) { LoadPasswdList(passwdList, &pwMapList); StrListFree(passwdList); @@ -2363,8 +2370,7 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args) keyLoadBuf = (byte*)WMALLOC(EXAMPLE_KEYLOAD_BUFFER_SZ, NULL, 0); if (keyLoadBuf == NULL) { - serverArgs->return_code = EXIT_FAILURE; - return 0; + ES_ERROR("Error allocating keyLoadBuf"); } #else keyLoadBuf = buf; @@ -2373,15 +2379,11 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args) bufSz = load_key(peerEcc, keyLoadBuf, bufSz); if (bufSz == 0) { - fprintf(stderr, "Couldn't load first key file.\n"); - serverArgs->return_code = EXIT_FAILURE; - return 0; + ES_ERROR("Couldn't load first key file.\n"); } if (wolfSSH_CTX_UsePrivateKey_buffer(ctx, keyLoadBuf, bufSz, WOLFSSH_FORMAT_ASN1) < 0) { - fprintf(stderr, "Couldn't use first key buffer.\n"); - serverArgs->return_code = EXIT_FAILURE; - return 0; + ES_ERROR("Couldn't use first key buffer.\n"); } #if !defined(WOLFSSH_NO_RSA) && !defined(WOLFSSH_NO_ECC) @@ -2390,18 +2392,15 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args) bufSz = load_key(peerEcc, keyLoadBuf, bufSz); if (bufSz == 0) { - fprintf(stderr, "Couldn't load second key file.\n"); - serverArgs->return_code = EXIT_FAILURE; - return 0; + ES_ERROR("Couldn't load second key file.\n"); } if (wolfSSH_CTX_UsePrivateKey_buffer(ctx, keyLoadBuf, bufSz, WOLFSSH_FORMAT_ASN1) < 0) { - fprintf(stderr, "Couldn't use second key buffer.\n"); - serverArgs->return_code = EXIT_FAILURE; - return 0; + ES_ERROR("Couldn't use second key buffer.\n"); } #endif + #ifndef NO_FILESYSTEM if (userPubKey) { byte* userBuf = NULL; word32 userBufSz = 0; @@ -2411,21 +2410,18 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args) /* create temp buffer and load in file */ if (userBufSz == 0) { - fprintf(stderr, "Couldn't find size of file %s.\n", userPubKey); - serverArgs->return_code = EXIT_FAILURE; - return 0; + ES_ERROR("Couldn't find size of file %s.\n", userPubKey); } userBuf = (byte*)WMALLOC(userBufSz, NULL, 0); if (userBuf == NULL) { - fprintf(stderr, "WMALLOC failed\n"); - serverArgs->return_code = EXIT_FAILURE; - return 0; + ES_ERROR("WMALLOC failed\n"); } load_file(userPubKey, userBuf, &userBufSz); LoadPublicKeyBuffer(userBuf, userBufSz, &pwMapList); WFREE(userBuf, NULL, 0); } + #endif #ifdef WOLFSSH_CERTS if (caCert) { @@ -2436,25 +2432,18 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args) load_file(caCert, NULL, &certBufSz); if (certBufSz == 0) { - fprintf(stderr, - "Couldn't find size of file %s.\n", caCert); - serverArgs->return_code = EXIT_FAILURE; - return 0; + ES_ERROR("Couldn't find size of file %s.\n", caCert); } certBuf = (byte*)WMALLOC(certBufSz, NULL, 0); if (certBuf == NULL) { - fprintf(stderr, "WMALLOC failed\n"); - serverArgs->return_code = EXIT_FAILURE; - return 0; + ES_ERROR("WMALLOC failed\n"); } load_file(caCert, certBuf, &certBufSz); ret = wolfSSH_CTX_AddRootCert_buffer(ctx, certBuf, certBufSz, WOLFSSH_FORMAT_PEM); if (ret != 0) { - fprintf(stderr, "Couldn't add root cert\n"); - serverArgs->return_code = EXIT_FAILURE; - return 0; + ES_ERROR("Couldn't add root cert\n"); } WFREE(certBuf, NULL, 0); } @@ -2500,9 +2489,7 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args) /* wait for network and storage device */ if (NETBOOT_Wait_For_Network_Up(NU_SUSPEND) != NU_SUCCESS) { - fprintf(stderr, "Couldn't find network.\r\n"); - serverArgs->return_code = EXIT_FAILURE; - return 0; + ES_ERROR("Couldn't find network.\r\n"); } for(i = 0; i < 15 && ret != NU_SUCCESS; i++) @@ -2513,9 +2500,7 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args) } if (ret != NU_SUCCESS) { - fprintf(stderr, "Couldn't find storage device.\r\n"); - serverArgs->return_code = EXIT_FAILURE; - return 0; + ES_ERROR("Couldn't find storage device.\r\n"); } } #endif @@ -2523,9 +2508,7 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args) /* if creating a ready file with port then override port to be 0 */ if (readyFile != NULL) { #ifdef NO_FILESYSTEM - fprintf(stderr, "cannot create readyFile with no file system.\r\n"); - serverArgs->return_code = EXIT_FAILURE; - return 0; + ES_ERROR("cannot create readyFile with no file system.\r\n"); #else port = 0; #endif @@ -2538,14 +2521,16 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args) int ret; ret = WFOPEN(NULL, &f, readyFile, "w"); if (f != NULL && ret == 0) { - fprintf(f, "%d\n", (int)port); + 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 = 0; + WS_SOCKET_T clientFd = WOLFSSH_SOCKET_INVALID; #ifdef WOLFSSL_NUCLEUS struct addr_struct clientAddr; #else @@ -2558,18 +2543,14 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args) threadCtx = (thread_ctx_t*)WMALLOC(sizeof(thread_ctx_t), NULL, 0); if (threadCtx == NULL) { - fprintf(stderr, "Couldn't allocate thread context data.\n"); - serverArgs->return_code = EXIT_FAILURE; - return 0; + 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); - fprintf(stderr, "Couldn't allocate SSH data.\n"); - serverArgs->return_code = EXIT_FAILURE; - return 0; + ES_ERROR("Couldn't allocate SSH data.\n"); } wolfSSH_SetUserAuthCtx(ssh, &pwMapList); /* Use the session object for its own highwater callback ctx */ @@ -2580,9 +2561,7 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args) #ifdef WOLFSSH_SFTP if (SetDefaultSftpPath(ssh, defaultSftpPath) != 0) { - fprintf(stderr, "Couldn't store default sftp path.\n"); - serverArgs->return_code = EXIT_FAILURE; - return 0; + ES_ERROR("Couldn't store default sftp path.\n"); } #endif @@ -2598,9 +2577,7 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args) /* 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) { - fprintf(stderr, "Couldn't find network.\r\n"); - serverArgs->return_code = EXIT_FAILURE; - return 0; + ES_ERROR("Couldn't find network.\r\n"); } WMEMCPY(ipaddr, &sock.ip_num, MAX_ADDRESS_SIZE); @@ -2618,9 +2595,7 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args) &clientAddrSz); #endif if (clientFd == -1) { - err_sys("tcp accept failed"); - serverArgs->return_code = EXIT_FAILURE; - return 0; + ES_ERROR("tcp accept failed"); } if (nonBlock) @@ -2649,23 +2624,21 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args) } while (multipleConnections && !quit); - if (listenFd != 0) { + if (listenFd != WOLFSSH_SOCKET_INVALID) { WCLOSESOCKET(listenFd); } wc_FreeMutex(&doneLock); PwMapListDelete(&pwMapList); wolfSSH_CTX_free(ctx); if (wolfSSH_Cleanup() != WS_SUCCESS) { - fprintf(stderr, "Couldn't clean up wolfSSH.\n"); - serverArgs->return_code = EXIT_FAILURE; - return 0; + 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; - return 0; + WOLFSSL_RETURN_FROM_THREAD(0); } #endif /* NO_WOLFSSH_SERVER */ diff --git a/examples/scpclient/scpclient.c b/examples/scpclient/scpclient.c index 3ee5a5334..a23fdef46 100644 --- a/examples/scpclient/scpclient.c +++ b/examples/scpclient/scpclient.c @@ -31,7 +31,8 @@ #endif #include -#if !defined(USE_WINDOWS_API) && !defined(MICROCHIP_PIC32) +#if !defined(USE_WINDOWS_API) && !defined(MICROCHIP_PIC32) && \ + !defined(WOLFSSH_ZEPHYR) #include #endif #include diff --git a/examples/server/server.c b/examples/server/server.c index 1136d0135..c74f78922 100644 --- a/examples/server/server.c +++ b/examples/server/server.c @@ -38,7 +38,7 @@ #include #include #include -#include "examples/server/server.h" +#include "server.h" #ifdef NO_FILESYSTEM #include @@ -760,12 +760,15 @@ THREAD_RETURN WOLFSSH_THREAD server_test(void* args) threadCtx->nonBlock = nonBlock; #ifndef SINGLE_THREADED - ThreadStart(server_worker, threadCtx, &thread); - +#if defined(WOLFSSH_OLD_THREADING) || defined(WOLFSSL_THREAD_NO_JOIN) if (multipleConnections) - ThreadDetach(thread); + ThreadStartNoJoin(server_worker, threadCtx); else +#endif + { + ThreadStart(server_worker, threadCtx, &thread); ThreadJoin(thread); + } #else server_worker(threadCtx); #endif /* SINGLE_THREADED */ @@ -781,7 +784,7 @@ THREAD_RETURN WOLFSSH_THREAD server_test(void* args) wc_ecc_fp_free(); /* free per thread cache */ #endif - return 0; + WOLFSSL_RETURN_FROM_THREAD(0); } #endif /* NO_WOLFSSH_SERVER */ diff --git a/examples/sftpclient/sftpclient.c b/examples/sftpclient/sftpclient.c index 2a5c795ca..adbb5df53 100644 --- a/examples/sftpclient/sftpclient.c +++ b/examples/sftpclient/sftpclient.c @@ -39,7 +39,8 @@ #include #include "examples/sftpclient/sftpclient.h" #include "examples/client/common.h" -#ifndef USE_WINDOWS_API +#if !defined(USE_WINDOWS_API) && !defined(MICROCHIP_PIC32) && \ + !defined(WOLFSSH_ZEPHYR) #include #endif @@ -379,7 +380,7 @@ static int doCmds(func_args* args) err_msg("fputs error"); return -1; } - fflush(stdout); + WFFLUSH(stdout); WMEMSET(msg, 0, sizeof(msg)); if (SFTP_FGETS(args, msg, sizeof(msg) - 1) == NULL) { @@ -1385,7 +1386,7 @@ THREAD_RETURN WOLFSSH_THREAD sftpclient_test(void* args) wc_ecc_fp_free(); /* free per thread cache */ #endif - return 0; + WOLFSSL_RETURN_FROM_THREAD(0); } #else @@ -1399,7 +1400,7 @@ THREAD_RETURN WOLFSSH_THREAD sftpclient_test(void* args) "Please recompile with WOLFSSH_SFTP or --enable-sftp\n"); #endif (void)args; - return 0; + WOLFSSL_RETURN_FROM_THREAD(0); } #endif /* WOLFSSH_SFTP */ diff --git a/src/internal.c b/src/internal.c index c90166903..098f51825 100644 --- a/src/internal.c +++ b/src/internal.c @@ -29,6 +29,7 @@ #include #endif +#include #include #include #include @@ -826,7 +827,7 @@ void SshResourceFree(WOLFSSH* ssh, void* heap) ssh->scpFileNameSz = 0; } if (ssh->scpRecvMsg) { - WFREE(ssh->scpRecvMsg, ssh->heap, DYNTYPE_STRING); + WFREE(ssh->scpRecvMsg, ssh->ctx->heap, DYNTYPE_STRING); ssh->scpRecvMsg = NULL; ssh->scpRecvMsgSz = 0; } @@ -1245,7 +1246,7 @@ static int SetHostPrivateKey(WOLFSSH_CTX* ctx, if (pvtKey->publicKeyFmt == keyId) { if (pvtKey->key != NULL) { ForceZero(pvtKey->key, pvtKey->keySz); - WFREE(pvtKey->key, heap, dynamicType); + WFREE(pvtKey->key, ctx->heap, dynamicType); } } else { @@ -2247,8 +2248,8 @@ int wolfSSH_SendPacket(WOLFSSH* ssh) int sent; /* sanity check on amount requested to be sent */ - if (ssh->outputBuffer.idx + ssh->outputBuffer.length > - ssh->outputBuffer.bufferSz) { + if (ssh->outputBuffer.length > ssh->outputBuffer.bufferSz || + ssh->outputBuffer.length < ssh->outputBuffer.idx) { WLOG(WS_LOG_ERROR, "Bad buffer state"); return WS_BUFFER_E; } @@ -8327,7 +8328,7 @@ int SendKexInit(WOLFSSH* ssh) byte* payload = NULL; char* kexAlgoNames = NULL; char* keyAlgoNames = NULL; - const byte* algo = 0; + const byte* algo = NULL; word32 algoCount = 0, idx = 0, payloadSz = 0, kexAlgoNamesSz = 0, keyAlgoNamesSz = 0; int ret = WS_SUCCESS; @@ -9055,7 +9056,7 @@ int SendKexDhReply(WOLFSSH* ssh) byte kPad = 0; word32 sigBlockSz = 0; word32 payloadSz = 0; - byte* output = 0; + byte* output = NULL; word32 idx = 0; word32 keyIdx = 0; byte msgId = MSGID_KEXDH_REPLY; diff --git a/src/io.c b/src/io.c index 6f1574360..a3e6af1cd 100644 --- a/src/io.c +++ b/src/io.c @@ -141,6 +141,8 @@ void* wolfSSH_GetIOWriteCtx(WOLFSSH* ssh) #include "nucleus.h" #include "networking/nu_networking.h" #include + #elif defined(WOLFSSH_ZEPHYR) + #include #else #include #include diff --git a/src/port.c b/src/port.c index 543c6dbb0..035019080 100644 --- a/src/port.c +++ b/src/port.c @@ -45,7 +45,8 @@ */ -#if !defined(NO_FILESYSTEM) && !defined(WOLFSSH_USER_FILESYSTEM) +#if !defined(NO_FILESYSTEM) && !defined(WOLFSSH_USER_FILESYSTEM) && \ + !defined(WOLFSSH_ZEPHYR) int wfopen(WFILE** f, const char* filename, const char* mode) { #ifdef USE_WINDOWS_API @@ -103,7 +104,7 @@ int wfopen(WFILE** f, const char* filename, const char* mode) !defined(NO_WOLFSSH_SERVER) #if defined(USE_WINDOWS_API) || defined(WOLFSSL_NUCLEUS) || \ - defined(FREESCALE_MQX) + defined(FREESCALE_MQX) || defined(WOLFSSH_ZEPHYR) /* This is current inline in the source. */ @@ -475,6 +476,145 @@ int WS_DeleteFileA(const char* fileName, void* heap) #endif /* USE_WINDOWS_API WOLFSSH_SFTP WOLFSSH_SCP */ +#if defined(WOLFSSH_ZEPHYR) && (defined(WOLFSSH_SFTP) || defined(WOLFSSH_SCP)) + +int wssh_z_fstat(const char *p, struct fs_dirent *b) +{ + size_t p_len; + + if (p == NULL || b == NULL) + return -1; + + p_len = WSTRLEN(p); + /* Detect if origin directory when it ends in ':' or ':/' */ + if (p_len >= 3 && (p[p_len-1] == ':' || + (p[p_len-1] == '/' && p[p_len-2] == ':'))) { + b->type = FS_DIR_ENTRY_DIR; + b->size = 0; + b->name[0] = '/'; + b->name[1] = '\0'; + return 0; + } + else + return fs_stat(p, b); +} + +int z_fs_chdir(const char *path) +{ + /* Just make sure that the path exists and is a directory */ + struct fs_dirent dir; + int ret; + + ret = wssh_z_fstat(path, &dir); + if (ret != 0 || dir.type != FS_DIR_ENTRY_DIR) + ret = -1; + return ret; +} + +static struct { + byte open:1; + WFILE zfp; +} z_fds[WOLFSSH_MAX_DESCIPRTORS]; +static wolfSSL_Mutex z_fds_mutex; +static int z_fds_setup = 0; + +int wssh_z_fds_init(void) +{ + int ret = 0; + if (!z_fds_setup) { + WMEMSET(z_fds, 0, sizeof(z_fds)); + ret = wc_InitMutex(&z_fds_mutex); + if (ret == 0) + z_fds_setup = 1; + } + return ret; +} + +int wssh_z_fds_cleanup(void) +{ + int ret = 0; + if (z_fds_setup) { + WMEMSET(z_fds, 0, sizeof(z_fds)); + ret = wc_FreeMutex(&z_fds_mutex); + z_fds_setup = 0; + } + return ret; +} + +WFD wssh_z_open(const char *p, int f) +{ + WFD ret = -1; + if (p != NULL) { + if (wc_LockMutex(&z_fds_mutex) == 0) { + WFD idx = 0; + /* find a free fd */ + while(idx < WOLFSSH_MAX_DESCIPRTORS && z_fds[idx].open) + idx++; + if (idx < WOLFSSH_MAX_DESCIPRTORS) { + /* found a free fd */ + fs_file_t_init(&z_fds[idx].zfp); + if (fs_open(&z_fds[idx].zfp, p, f) == 0) { + z_fds[idx].open = 1; + ret = idx; + } + } + wc_UnLockMutex(&z_fds_mutex); + } + } + return ret; +} + +int wssh_z_close(WFD fd) +{ + int ret = -1; + if (fd >= 0 && fd < WOLFSSH_MAX_DESCIPRTORS) { + if (wc_LockMutex(&z_fds_mutex) == 0) { + if (z_fds[fd].open) { + z_fds[fd].open = 0; + if (fs_close(&z_fds[fd].zfp) == 0) + ret = 0; + } + wc_UnLockMutex(&z_fds_mutex); + } + } + return ret; +} + +int wPwrite(WFD fd, unsigned char* buf, unsigned int sz, + const unsigned int* shortOffset) +{ + int ret = -1; + if (fd >= 0 && fd < WOLFSSH_MAX_DESCIPRTORS) { + if (wc_LockMutex(&z_fds_mutex) == 0) { + if (z_fds[fd].open) { + const word32* offset = (const word32*)shortOffset; + if (fs_seek(&z_fds[fd].zfp, offset[0], FS_SEEK_SET) == 0) + ret = fs_write(&z_fds[fd].zfp, buf, sz); + } + wc_UnLockMutex(&z_fds_mutex); + } + } + return ret; +} + +int wPread(WFD fd, unsigned char* buf, unsigned int sz, + const unsigned int* shortOffset) +{ + int ret = -1; + if (fd >= 0 && fd < WOLFSSH_MAX_DESCIPRTORS) { + if (wc_LockMutex(&z_fds_mutex) == 0) { + if (z_fds[fd].open) { + const word32* offset = (const word32*)shortOffset; + if (fs_seek(&z_fds[fd].zfp, offset[0], FS_SEEK_SET) == 0) + ret = fs_read(&z_fds[fd].zfp, buf, sz); + } + wc_UnLockMutex(&z_fds_mutex); + } + } + return ret; +} + +#endif #ifndef WSTRING_USER diff --git a/src/ssh.c b/src/ssh.c index 56d65722b..93a5df572 100644 --- a/src/ssh.c +++ b/src/ssh.c @@ -71,6 +71,10 @@ int wolfSSH_Init(void) #ifdef WC_RNG_SEED_CB wc_SetSeed_Cb(wc_GenerateSeed); #endif +#if defined(WOLFSSH_ZEPHYR) && (defined(WOLFSSH_SFTP) || defined(WOLFSSH_SCP)) + if (wssh_z_fds_init() != 0) + ret = WS_CRYPTO_FAILED; +#endif WLOG(WS_LOG_DEBUG, "Leaving wolfSSH_Init(), returning %d", ret); return ret; @@ -85,6 +89,10 @@ int wolfSSH_Cleanup(void) if (wolfCrypt_Cleanup() != 0) ret = WS_CRYPTO_FAILED; +#if defined(WOLFSSH_ZEPHYR) && (defined(WOLFSSH_SFTP) || defined(WOLFSSH_SCP)) + if (wssh_z_fds_cleanup() != 0) + ret = WS_CRYPTO_FAILED; +#endif WLOG(WS_LOG_DEBUG, "Leaving wolfSSH_Cleanup(), returning %d", ret); return ret; @@ -1317,6 +1325,7 @@ void* wolfSSH_GetPublicKeyCheckCtx(WOLFSSH* ssh) #ifdef WOLFSSH_TERM +#if defined(WOLFSSH_TERM) && !defined(NO_FILESYSTEM) /* Used to resize terminal window with shell connections * returns WS_SUCCESS on success */ int wolfSSH_ChangeTerminalSize(WOLFSSH* ssh, word32 columns, word32 rows, @@ -1350,6 +1359,7 @@ void wolfSSH_SetTerminalResizeCtx(WOLFSSH* ssh, void* usrCtx) { ssh->termCtx = usrCtx; } +#endif #endif @@ -2383,7 +2393,14 @@ int wolfSSH_RealPath(const char* defaultPath, char* in, char* prev = strrchr(out, '/'); if (prev != NULL) { - if (prev != out) { + if (prev != out +#ifdef WOLFSSH_ZEPHYR + /* Zephyr FAT fs path names follow the format of '/RAM:' + * and we want to preserve the '/' after this mount + * point definition too. */ + && prev[-1] != ':' +#endif + ) { prev[0] = 0; curSz = (word32)WSTRLEN(out); } diff --git a/src/wolfscp.c b/src/wolfscp.c index c568ed4d0..d51912cfc 100644 --- a/src/wolfscp.c +++ b/src/wolfscp.c @@ -1980,7 +1980,7 @@ int wsScpRecvCallback(WOLFSSH* ssh, int state, const char* basePath, #ifdef WOLFSCP_FLUSH flush_bytes += bytes; if (flush_bytes >= WRITE_FLUSH_SIZE) { - if (fflush(fp) != 0) + if (WFFLUSH(fp) != 0) WLOG(WS_LOG_ERROR, scpError, "scp fflush failed", 0); if (fsync(fileno(fp)) != 0) WLOG(WS_LOG_ERROR, scpError, "scp fsync failed", 0); @@ -1996,7 +1996,7 @@ int wsScpRecvCallback(WOLFSSH* ssh, int state, const char* basePath, /* close file */ if (fp != NULL) { #ifdef WOLFSCP_FLUSH - (void)fflush(fp); + (void)WFFLUSH(fp); (void)fsync(fileno(fp)); flush_bytes = 0; #endif @@ -2011,7 +2011,7 @@ int wsScpRecvCallback(WOLFSSH* ssh, int state, const char* basePath, ret = WS_SCP_CONTINUE; } else { WLOG(WS_LOG_ERROR, - "scp: unable to get timestamp info, abort"); + "scp: unable to set timestamp info, abort"); ret = WS_SCP_ABORT; } } @@ -2163,6 +2163,20 @@ static int GetFileStats(void *fs, ScpSendCtx* ctx, const char* fileName, *mTime = ctx->s.fupdate; *aTime = ctx->s.faccdate; NU_Done(&ctx->s); + #elif defined(WOLFSSH_ZEPHYR) + /* No time data in zephyr fs */ + *mTime = (word64)0; + *aTime = (word64)0; + /* Default perms */ + *fileMode = 0755; + /* Mimic S_IFMT */ + if (ctx->s.type == FS_DIR_ENTRY_FILE) + *fileMode |= 0040000; + else if (ctx->s.type == FS_DIR_ENTRY_DIR) + *fileMode |= 0100000; + else + ret = WS_BAD_FILE_E; + #else *mTime = (word64)ctx->s.st_mtime; *aTime = (word64)ctx->s.st_atime; @@ -2214,7 +2228,7 @@ static ScpDir* ScpNewDir(void *fs, const char* path, void* heap) } #else if (WOPENDIR(fs, heap, &entry->dir, path) != 0 - #ifndef WOLFSSL_NUCLEUS + #if !defined(WOLFSSL_NUCLEUS) && !defined(WOLFSSH_ZEPHYR) || entry->dir == NULL #endif ) { @@ -2359,6 +2373,13 @@ static int FindNextDirEntry(void *fs, ScpSendCtx* ctx) } while ((ctx->entry != NULL) && (((WSTRLEN(ctx->entry) == 1) && WSTRNCMP(ctx->entry, ".", 1) == 0) || ((WSTRLEN(ctx->entry) == 2) && WSTRNCMP(ctx->entry, "..", 2) == 0))); +#elif defined(WOLFSSH_ZEPHYR) + do { + if (fs_readdir(&ctx->currentDir->dir, &ctx->entry) != 0) + return WS_FATAL_ERROR; + if (ctx->entry.name[0] == 0) /* Reached end-of-dir */ + return WS_NEXT_ERROR; + } while (1); #else do { ctx->entry = WREADDIR(fs, &ctx->currentDir->dir); @@ -2391,6 +2412,8 @@ int ScpFileIsDir(ScpSendCtx* ctx) return (ctx->s.fattribute & ADIRENT); #elif defined(USE_WINDOWS_API) return (ctx->s.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY); +#elif defined(WOLFSSH_ZEPHYR) + return ctx->s.type == FS_DIR_ENTRY_DIR; #else return S_ISDIR(ctx->s.st_mode); #endif @@ -2402,6 +2425,8 @@ static int ScpFileIsFile(ScpSendCtx* ctx) return (ctx->s.fattribute != ADIRENT); #elif defined(USE_WINDOWS_API) return ((ctx->s.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0); +#elif defined(WOLFSSH_ZEPHYR) + return ctx->s.type == FS_DIR_ENTRY_FILE; #else return S_ISREG(ctx->s.st_mode); #endif @@ -2441,6 +2466,8 @@ static int ScpProcessEntry(WOLFSSH* ssh, char* fileName, word64* mTime, GetFullPathNameA(fileName, MAX_PATH, path, NULL); dNameLen = (int)WSTRLEN(path); } + #elif defined(WOLFSSH_ZEPHYR) + dNameLen = (int)WSTRLEN(sendCtx->entry.name); #else dNameLen = (int)WSTRLEN(sendCtx->entry->d_name); #endif @@ -2466,6 +2493,11 @@ static int ScpProcessEntry(WOLFSSH* ssh, char* fileName, word64* mTime, DEFAULT_SCP_FILE_NAME_SZ); WSTRNCPY(fileName, sendCtx->entry, DEFAULT_SCP_FILE_NAME_SZ); + #elif defined(WOLFSSH_ZEPHYR) + WSTRNCAT(filePath, sendCtx->entry.name, + DEFAULT_SCP_FILE_NAME_SZ); + WSTRNCPY(fileName, sendCtx->entry.name, + DEFAULT_SCP_FILE_NAME_SZ); #else WSTRNCAT(filePath, sendCtx->entry->d_name, DEFAULT_SCP_FILE_NAME_SZ); @@ -2715,7 +2747,7 @@ int wsScpSendCallback(WOLFSSH* ssh, int state, const char* peerRequest, if (ret == WS_SUCCESS || ret == WS_NEXT_ERROR) { - #ifdef WOLFSSL_NUCLEUS + #if defined(WOLFSSL_NUCLEUS) || defined(WOLFSSH_ZEPHYR) if (ret == WS_NEXT_ERROR) { #else /* reached end of directory */ diff --git a/src/wolfsftp.c b/src/wolfsftp.c index 67c02d200..d50792fd3 100644 --- a/src/wolfsftp.c +++ b/src/wolfsftp.c @@ -1217,7 +1217,7 @@ static int wolfSSH_SFTP_RecvRealPath(WOLFSSH* ssh, int reqId, byte* data, char s[WOLFSSH_MAX_FILENAME]; word32 rSz, sSz; word32 lidx = 0; - int ret; + int ret = 0; byte* out; word32 outSz = 0; @@ -1245,10 +1245,13 @@ static int wolfSSH_SFTP_RecvRealPath(WOLFSSH* ssh, int reqId, byte* data, /* If the default path isn't set, try to get it. */ if (ssh->sftpDefaultPath == NULL) { char wd[WOLFSSH_MAX_FILENAME]; + WMEMSET(wd, 0, WOLFSSH_MAX_FILENAME); ret = WS_SUCCESS; - #ifndef USE_WINDOWS_API + #ifdef WOLFSSH_ZEPHYR + WSTRNCPY(wd, CONFIG_WOLFSSH_SFTP_DEFAULT_DIR, WOLFSSH_MAX_FILENAME); + #elif !defined(USE_WINDOWS_API) if (WGETCWD(ssh->fs, wd, sizeof(wd)-1) == NULL) { ret = WS_INVALID_PATH_E; } @@ -1467,7 +1470,7 @@ int wolfSSH_SFTP_read(WOLFSSH* ssh) wolfSSH_SFTP_buffer_data(&state->buffer), wolfSSH_SFTP_buffer_size(&state->buffer)); break; - #ifndef _WIN32_WCE + #if !defined(_WIN32_WCE) && !defined(WOLFSSH_ZEPHYR) case WOLFSSH_FTP_SETSTAT: ret = wolfSSH_SFTP_RecvSetSTAT(ssh, state->reqId, wolfSSH_SFTP_buffer_data(&state->buffer), @@ -2959,6 +2962,72 @@ static int wolfSSH_SFTPNAME_readdir(WOLFSSH* ssh, WDIR* dir, WS_SFTPNAME* out, return WS_SUCCESS; } +#elif defined(WOLFSSH_ZEPHYR) + +/* helper function that gets file information from reading directory + * + * returns WS_SUCCESS on success + */ +static int wolfSSH_SFTPNAME_readdir(WOLFSSH* ssh, WDIR* dir, WS_SFTPNAME* out, + char* dirName) +{ + struct fs_dirent dp; + int sz; + + if (dir == NULL || ssh == NULL || out == NULL) { + return WS_BAD_ARGUMENT; + } + + /* 0 return and dp.name[0] == 0 means end-of-dir */ + if (fs_readdir(dir, &dp) != 0 || dp.name[0] == 0) { + return WS_FATAL_ERROR; + } + + sz = (int)WSTRLEN(dp.name); + out->fName = (char*)WMALLOC(sz + 1, out->heap, DYNTYPE_SFTP); + if (out->fName == NULL) { + return WS_MEMORY_E; + } + + WMEMCPY(out->fName, dp.name, sz); + out->fName[sz] = '\0'; + out->fSz = sz; + + /* attempt to get file attributes. Could be directory or have none */ + { + char r[WOLFSSH_MAX_FILENAME]; + char s[WOLFSSH_MAX_FILENAME]; + + if ((WSTRLEN(dirName) + WSTRLEN(out->fName) + 2) > sizeof(r)) { + WLOG(WS_LOG_SFTP, "Path length too large"); + WFREE(out->fName, out->heap, DYNTYPE_SFTP); + return WS_FATAL_ERROR; + } + WSNPRINTF(r, sizeof(r), "%s/%s", dirName, out->fName); + + if (wolfSSH_RealPath(ssh->sftpDefaultPath, r, s, sizeof(s)) < 0) { + WFREE(out->fName, out->heap, DYNTYPE_SFTP); + WLOG(WS_LOG_SFTP, "Error cleaning path to get attributes"); + return WS_FATAL_ERROR; + } + + if (SFTP_GetAttributes(ssh->fs, s, &out->atrb, 0, ssh->ctx->heap) + != WS_SUCCESS) { + WLOG(WS_LOG_SFTP, "Unable to get attribute values for %s", + out->fName); + } + } + + /* Use attributes and fName to create long name */ + if (SFTP_CreateLongName(out) != WS_SUCCESS) { + WLOG(WS_LOG_DEBUG, "Error creating long name for %s", out->fName); + WFREE(out->fName, out->heap, DYNTYPE_SFTP); + return WS_FATAL_ERROR; + } + + return WS_SUCCESS; +} + #else /* helper function that gets file information from reading directory @@ -3108,7 +3177,7 @@ int wolfSSH_SFTP_SetDefaultPath(WOLFSSH* ssh, const char* path) */ int wolfSSH_SFTP_RecvReadDir(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz) { - WDIR dir; + WDIR* dir = NULL; word32 handle[2] = {0, 0}; word32 sz; word32 idx = 0; @@ -3153,7 +3222,7 @@ int wolfSSH_SFTP_RecvReadDir(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz) /* find DIR given handle */ while (cur != NULL) { if (cur->id[0] == handle[0] && cur->id[1] == handle[1]) { - dir = cur->dir; + dir = &cur->dir; dirName = cur->dirName; break; } @@ -3170,7 +3239,7 @@ int wolfSSH_SFTP_RecvReadDir(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz) if (!cur->isEof) { do { name = wolfSSH_SFTPNAME_new(ssh->ctx->heap); - ret = wolfSSH_SFTPNAME_readdir(ssh, &dir, name, dirName); + ret = wolfSSH_SFTPNAME_readdir(ssh, dir, name, dirName); if (ret == WS_SUCCESS || ret == WS_NEXT_ERROR) { count++; outSz += name->fSz + name->lSz + (UINT32_SZ * 2); @@ -4624,6 +4693,57 @@ static int SFTP_GetAttributes_Handle(WOLFSSH* ssh, byte* handle, int handleSz, return WS_SUCCESS; } +#elif defined(WOLFSSH_ZEPHYR) + +static int PopulateAttributes(WS_SFTP_FILEATRB* atr, WSTAT_T* stats) +{ + WMEMSET(atr, 0, sizeof(WS_SFTP_FILEATRB)); + + atr->flags |= WOLFSSH_FILEATRB_SIZE; + atr->sz[0] = (word32)(stats->size & 0xFFFFFFFF); + + atr->flags |= WOLFSSH_FILEATRB_PERM; + /* Default perms */ + atr->per = 0755; + /* Mimic S_IFMT */ + if (stats->type == FS_DIR_ENTRY_FILE) + atr->per |= 0040000; + else if (stats->type == FS_DIR_ENTRY_DIR) + atr->per |= 0100000; + else + return WS_BAD_FILE_E; + + return WS_SUCCESS; +} + +int SFTP_GetAttributes(void* fs, const char* fileName, WS_SFTP_FILEATRB* atr, + byte noFollow, void* heap) +{ + WSTAT_T stats; + + WOLFSSH_UNUSED(heap); + WOLFSSH_UNUSED(noFollow); + + if (WSTAT(fs, fileName, &stats) != 0) { + return WS_BAD_FILE_E; + } + + return PopulateAttributes(atr, &stats); +} + +int SFTP_GetAttributes_Handle(WOLFSSH* ssh, byte* handle, int handleSz, + WS_SFTP_FILEATRB* atr) +{ + WOLFSSH_UNUSED(ssh); + WOLFSSH_UNUSED(handle); + WOLFSSH_UNUSED(handleSz); + WOLFSSH_UNUSED(atr); + + WLOG(WS_LOG_SFTP, "SFTP_GetAttributes_Handle() not implemented yet"); + return WS_NOT_COMPILED; +} + + #elif defined(WOLFSSH_USER_FILESYSTEM) /* User-defined I/O support */ #else @@ -4643,12 +4763,12 @@ int SFTP_GetAttributes(void* fs, const char* fileName, WS_SFTP_FILEATRB* atr, if (noFollow) { /* Note, for windows, we treat WSTAT and WLSTAT the same. */ - if (WLSTAT(ssh->fs, fileName, &stats) != 0) { + if (WLSTAT(fs, fileName, &stats) != 0) { return WS_BAD_FILE_E; } } else { - if (WSTAT(ssh->fs, fileName, &stats) != 0) { + if (WSTAT(fs, fileName, &stats) != 0) { return WS_BAD_FILE_E; } } @@ -4693,7 +4813,7 @@ int SFTP_GetAttributes_Handle(WOLFSSH* ssh, byte* handle, int handleSz, WLOG(WS_LOG_SFTP, "Unexpected handle size SFTP_GetAttributes_Handle()"); } - if (fstat(*(int*)handle, &stats) != 0) { + if (WFSTAT(ssh->fs, *(int*)handle, &stats) != 0) { return WS_BAD_FILE_E; } @@ -4968,7 +5088,7 @@ int wolfSSH_SFTP_RecvLSTAT(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz) } -#ifndef USE_WINDOWS_API +#if !defined(USE_WINDOWS_API) && !defined(WOLFSSH_ZEPHYR) /* Set the files mode * return WS_SUCCESS on success */ static int SFTP_SetMode(WOLFSSH* ssh, char* name, word32 mode) { @@ -4981,7 +5101,7 @@ static int SFTP_SetMode(WOLFSSH* ssh, char* name, word32 mode) { #endif -#ifndef _WIN32_WCE +#if !defined(_WIN32_WCE) && !defined(WOLFSSH_ZEPHYR) /* sets a files attributes * returns WS_SUCCESS on success */ @@ -4999,7 +5119,7 @@ static int SFTP_SetFileAttributes(WOLFSSH* ssh, char* name, WS_SFTP_FILEATRB* at /* @TODO set group and user id */ } -#ifndef USE_WINDOWS_API +#if !defined(USE_WINDOWS_API) && !defined(WOLFSSH_ZEPHYR) /* check if permissions attribute present */ if (atr->flags & WOLFSSH_FILEATRB_PERM) { ret = SFTP_SetMode(ssh, name, atr->per); diff --git a/tests/api.c b/tests/api.c index 840a0d4fa..1e098fdfb 100644 --- a/tests/api.c +++ b/tests/api.c @@ -27,6 +27,7 @@ #else #include #endif +#include #include #include @@ -59,13 +60,24 @@ char* myoptarg = NULL; #define WABORT() #endif -#define Fail(description, result) do { \ +#define PrintError(description, result) do { \ printf("\nERROR - %s line %d failed with:", __FILE__, __LINE__); \ - fputs("\n expected: ", stdout); printf description; \ - fputs("\n result: ", stdout); printf result; fputs("\n\n", stdout); \ - fflush(stdout); \ + printf("\n expected: "); printf description; \ + printf("\n result: "); printf result; printf("\n\n"); \ +} while(0) + +#ifdef WOLFSSH_ZEPHYR +#define Fail(description, result) do { \ + PrintError(description, result); \ + WABORT(); \ +} while(0) +#else +#define Fail(description, result) do { \ + PrintError(description, result); \ + WFFLUSH(stdout); \ WABORT(); \ } while(0) +#endif #define Assert(test, description, result) if (!(test)) Fail(description, result) @@ -846,6 +858,10 @@ static void test_wolfSSH_SFTP_SendReadPacket(void) wolfSSH_free(ssh); wolfSSH_CTX_free(ctx); +#ifdef WOLFSSH_ZEPHYR + /* Weird deadlock without this sleep */ + k_sleep(Z_TIMEOUT_TICKS(100)); +#endif ThreadJoin(serThread); } diff --git a/tests/sftp.c b/tests/sftp.c index 2094879d3..ef19ca0b7 100644 --- a/tests/sftp.c +++ b/tests/sftp.c @@ -23,6 +23,10 @@ #endif #include +#include + +#if defined(WOLFSSH_SFTP) && !defined(SINGLE_THREADED) + #include #include @@ -34,16 +38,22 @@ #include "examples/echoserver/echoserver.h" #include "examples/sftpclient/sftpclient.h" -#if defined(WOLFSSH_SFTP) && !defined(SINGLE_THREADED) - static const char* cmds[] = { "mkdir a", "cd a", "pwd", "ls", +#ifdef WOLFSSH_ZEPHYR + "put " CONFIG_WOLFSSH_SFTP_DEFAULT_DIR "/configure", +#else "put configure", +#endif "ls", +#ifdef WOLFSSH_ZEPHYR + "get configure " CONFIG_WOLFSSH_SFTP_DEFAULT_DIR "/test-get", +#else "get configure test-get", +#endif "rm configure", "cd ../", "ls", @@ -85,11 +95,19 @@ static int Expected(int command) case 4: { +#ifdef WOLFSSH_ZEPHYR + /* No . and .. in zephyr fs API */ + char expt1[] = "wolfSSH sftp> "; + char expt2[] = "wolfSSH sftp> "; +#else char expt1[] = ".\n..\nwolfSSH sftp> "; char expt2[] = "..\n.\nwolfSSH sftp> "; +#endif if (WMEMCMP(expt1, inBuf, sizeof(expt1)) != 0 && WMEMCMP(expt2, inBuf, sizeof(expt2)) != 0) { - fprintf(stderr, "Unexpected string of %s\n", inBuf); + printf("unexpected ls\n"); + printf("\texpected \n%s\n\tor\n%s\n\tbut got\n%s\n", expt1, + expt2, inBuf); return -1; } else @@ -166,7 +184,8 @@ int wolfSSH_SftpTest(int flag) char portNumber[8]; THREAD_TYPE serThread; - THREAD_TYPE cliThread; + + wolfSSH_Init(); WMEMSET(&ser, 0, sizeof(func_args)); WMEMSET(&cli, 0, sizeof(func_args)); @@ -212,11 +231,15 @@ int wolfSSH_SftpTest(int flag) cli.argc = argsCount; cli.signal = &ready; cli.sftp_cb = commandCb; - ThreadStart(sftpclient_test, (void*)&cli, &cliThread); + sftpclient_test(&cli); +#ifdef WOLFSSH_ZEPHYR + /* Weird deadlock without this sleep */ + k_sleep(Z_TIMEOUT_TICKS(100)); +#endif ThreadJoin(serThread); - ThreadJoin(cliThread); + wolfSSH_Cleanup(); return ret; } diff --git a/tests/testsuite.c b/tests/testsuite.c index 0b64266ac..8ee4a7c38 100644 --- a/tests/testsuite.c +++ b/tests/testsuite.c @@ -134,7 +134,7 @@ int wolfSSH_TestsuiteTest(int argc, char** argv) WSTRNCPY(serverArgv[serverArgc++], "echoserver", ARGLEN); WSTRNCPY(serverArgv[serverArgc++], "-1", ARGLEN); WSTRNCPY(serverArgv[serverArgc++], "-f", ARGLEN); - #ifndef USE_WINDOWS_API + #if !defined(USE_WINDOWS_API) && !defined(WOLFSSH_ZEPHYR) WSTRNCPY(serverArgv[serverArgc++], "-p", ARGLEN); WSTRNCPY(serverArgv[serverArgc++], "-0", ARGLEN); #endif @@ -150,7 +150,7 @@ int wolfSSH_TestsuiteTest(int argc, char** argv) WSTRNCPY(cA[clientArgc++], "client", ARGLEN); WSTRNCPY(cA[clientArgc++], "-u", ARGLEN); WSTRNCPY(cA[clientArgc++], "jill", ARGLEN); - #ifndef USE_WINDOWS_API + #if !defined(USE_WINDOWS_API) && !defined(WOLFSSH_ZEPHYR) WSTRNCPY(cA[clientArgc++], "-p", ARGLEN); WSNPRINTF(cA[clientArgc++], ARGLEN, "%d", ready.port); #endif @@ -166,6 +166,10 @@ int wolfSSH_TestsuiteTest(int argc, char** argv) return clientArgs.return_code; } +#ifdef WOLFSSH_ZEPHYR + /* Weird deadlock without this sleep */ + k_sleep(Z_TIMEOUT_TICKS(100)); +#endif ThreadJoin(serverThread); wolfSSH_Cleanup(); @@ -174,8 +178,10 @@ int wolfSSH_TestsuiteTest(int argc, char** argv) #ifdef WOLFSSH_SFTP printf("testing SFTP blocking\n"); wolfSSH_SftpTest(0); +#ifndef WOLFSSH_NO_NONBLOCKING printf("testing SFTP non blocking\n"); wolfSSH_SftpTest(1); +#endif #endif return EXIT_SUCCESS; diff --git a/tests/unit.c b/tests/unit.c index 48c54fc2a..5c9898d3f 100644 --- a/tests/unit.c +++ b/tests/unit.c @@ -35,7 +35,7 @@ #define WOLFSSH_TEST_HEX2BIN #include -#include "tests/unit.h" +#include "unit.h" /* Key Derivation Function (KDF) Unit Test */ diff --git a/wolfssh/port.h b/wolfssh/port.h index 5b96e0622..ce2503c5f 100644 --- a/wolfssh/port.h +++ b/wolfssh/port.h @@ -351,6 +351,38 @@ extern "C" { #define WOPENDIR(fs,h,c,d) f_opendir((c),(d)) #define WCLOSEDIR(fs,d) f_closedir(d) #endif +#elif defined(WOLFSSH_ZEPHYR) + + #include + #include + #include + + #define WFFLUSH(s) ((void)(s)) + + #define WFILE struct fs_file_t + + #define FLUSH_STD(a) + + int z_fs_chdir(const char *path); + + /* Use wolfCrypt z_fs_open and z_fs_close */ + #define WFOPEN(fs,f,fn,m) ((*(f) = z_fs_open((fn),(m))) == NULL) + #define WFCLOSE(fs,f) z_fs_close(f) + #define WFREAD(fs,b,s,a,f) fs_read((f),(b),(s)*(a)) + #define WFWRITE(fs,b,s,a,f) fs_write((f),(b),(s)*(a)) + #define WFSEEK(fs,s,o,w) fs_seek((s),(o),(w)) + #define WFTELL(fs,s) fs_tell((s)) + #define WREWIND(fs,s) fs_seek((s), 0, FS_SEEK_SET) + #define WSEEK_END FS_SEEK_END + #define WBADFILE NULL + #define WCHMOD(fs,f,m) chmod((f),(m)) + #undef WFGETS + #define WFGETS(b,s,f) NULL /* Not ported yet */ + #undef WFPUTS + #define WFPUTS(b,s) EOF /* Not ported yet */ + #define WUTIMES(a,b) (0) /* Not ported yet */ + #define WCHDIR(fs,b) z_fs_chdir((b)) + #elif defined(WOLFSSH_USER_FILESYSTEM) /* User-defined I/O support */ #else @@ -361,12 +393,15 @@ extern "C" { #define WFILE FILE WOLFSSH_API int wfopen(WFILE**, const char*, const char*); + #define WFFLUSH fflush + #define WFOPEN(fs,f,fn,m) wfopen((f),(fn),(m)) #define WFCLOSE(fs,f) fclose(f) #define WFREAD(fs,b,s,a,f) fread((b),(s),(a),(f)) #define WFWRITE(fs,b,s,a,f) fwrite((b),(s),(a),(f)) #define WFSEEK(fs,s,o,w) fseek((s),(o),(w)) #define WFTELL(fs,s) ftell((s)) + #define WFSTAT(fs,fd,b) fstat((fd),(b)) #define WREWIND(fs,s) rewind((s)) #define WSEEK_END SEEK_END #define WBADFILE NULL @@ -481,7 +516,9 @@ extern "C" { #define WVSNPRINTF(s,n,f,...) vsnprintf((s),(n),(f),__VA_ARGS__) #define WSTRTOK(s1,s2,s3) strtok_r((s1),(s2),(s3)) #else - #ifndef FREESCALE_MQX + #ifdef WOLFSSH_ZEPHYR + #include + #elif !defined(FREESCALE_MQX) #include #endif #define WSTRNCPY(s1,s2,n) strncpy((s1),(s2),(n)) @@ -518,6 +555,9 @@ extern "C" { #define WTIME(t1) mqx_time((t1)) #define WLOCALTIME(c,r) (localtime_r((c),(r))!=NULL) #define WOLFSSH_NO_TIMESTAMP /* no strftime() */ +#elif defined(WOLFSSH_ZEPHYR) + #define WTIME time + #define WLOCALTIME(c,r) (gmtime_r((c),(r))!=NULL) #else #define WTIME time #define WLOCALTIME(c,r) (localtime_r((c),(r))!=NULL) @@ -1221,6 +1261,50 @@ extern "C" { #define WDIR HANDLE #endif /* NO_WOLFSSH_DIR */ +#elif defined(WOLFSSH_ZEPHYR) + + #include + + #define WDIR struct fs_dir_t + #define WSTAT_T struct fs_dirent + + /* FAT_FS fs_stat doesn't handling stat'ing the top level dir. Let's wrap + * and implement that. */ + int wssh_z_fstat(const char *p, struct fs_dirent *b); + + #define WOPENDIR(fs,h,c,d) (fs_dir_t_init((c)), fs_opendir((c),(d))) + #define WCLOSEDIR(fs,d) fs_closedir((d)) + #define WMKDIR(fs,p,m) fs_mkdir((p)) + #define WRMDIR(fs,d) fs_unlink((d)) + #define WSTAT(fs,p,b) wssh_z_fstat((p),(b)) + #define WREMOVE(fs,d) fs_unlink((d)) + #define WRENAME(fs,o,n) fs_rename((o),(n)) + #define WS_DELIM '/' + + #define WOLFSSH_O_RDWR FS_O_RDWR + #define WOLFSSH_O_RDONLY FS_O_READ + #define WOLFSSH_O_WRONLY FS_O_WRITE + #define WOLFSSH_O_APPEND FS_O_APPEND + #define WOLFSSH_O_CREAT FS_O_CREATE + #define WOLFSSH_O_TRUNC 0 + #define WOLFSSH_O_EXCL 0 + + /* Our "file descriptor" wrapper */ + #ifndef WOLFSSH_MAX_DESCIPRTORS + #define WOLFSSH_MAX_DESCIPRTORS 10 + #endif + #define WFD int + int wssh_z_fds_init(void); + int wssh_z_fds_cleanup(void); + WFD wssh_z_open(const char *p, int f); + #define WOPEN(fs,p,f,m) wssh_z_open((p),(f)) + int wssh_z_close(WFD fd); + #define WCLOSE(fs,fd) wssh_z_close((fd)) + int wPwrite(WFD, unsigned char*, unsigned int, const unsigned int*); + int wPread(WFD, unsigned char*, unsigned int, const unsigned int*); + #define WPWRITE(fs,fd,b,s,o) wPwrite((fd),(b),(s),(o)) + #define WPREAD(fs,fd,b,s,o) wPread((fd),(b),(s),(o)) + #elif defined(WOLFSSH_USER_FILESYSTEM) /* User-defined I/O support */ #include "myFilesystem.h" diff --git a/wolfssh/settings.h b/wolfssh/settings.h index 8e11473c1..e4aa01664 100644 --- a/wolfssh/settings.h +++ b/wolfssh/settings.h @@ -38,6 +38,10 @@ #include "wolfSSL.I-CUBE-wolfSSH_conf.h" #endif +#if defined(WOLFSSH_ZEPHYR) && defined(CONFIG_WOLFSSH_SETTINGS_FILE) + #include CONFIG_WOLFSSH_SETTINGS_FILE +#endif + #ifdef __cplusplus extern "C" { #endif diff --git a/wolfssh/test.h b/wolfssh/test.h index 7b0c46b8d..b4db3b4d5 100644 --- a/wolfssh/test.h +++ b/wolfssh/test.h @@ -126,6 +126,35 @@ #endif #define SOCKET_T int #define NUM_SOCKETS 5 +#elif defined(WOLFSSH_ZEPHYR) + #include + #include + #include + #include + #include + #include + #include + #include + #define SOCKET_T int + #define NUM_SOCKETS 5 +#if (defined(WOLFSSH_TEST_CLIENT) || defined(WOLFSSH_TEST_SERVER)) && \ + !defined(TEST_IPV6) + static unsigned long inet_addr(const char *cp) + { + unsigned int a[4]; unsigned long ret; + int i, j; + for (i=0, j=0; i<4; i++) { + a[i] = 0; + while (cp[j] != '.' && cp[j] != '\0') { + a[i] *= 10; + a[i] += cp[j] - '0'; + j++; + } + } + ret = ((a[3]<<24) + (a[2]<<16) + (a[1]<<8) + a[0]) ; + return(ret) ; + } +#endif #elif defined(WOLFSSH_USER_IO) #include #include @@ -169,7 +198,7 @@ #elif defined(WOLFSSH_TIRTOS) #define WOLFSSH_SOCKET_INVALID ((SOCKET_T)-1) #else - #define WOLFSSH_SOCKET_INVALID (SOCKET_T)(0) + #define WOLFSSH_SOCKET_INVALID (SOCKET_T)(-1) #endif #endif /* WOLFSSH_SOCKET_INVALID */ @@ -222,7 +251,9 @@ #define serverKeyRsaPemFile "./keys/server-key-rsa.pem" -#ifndef TEST_IPV6 +#ifdef WOLFSSH_ZEPHYR + static const char* const wolfSshIp = "192.0.2.1"; +#elif !defined(TEST_IPV6) static const char* const wolfSshIp = "127.0.0.1"; #else /* TEST_IPV6 */ static const char* const wolfSshIp = "::1"; @@ -252,6 +283,12 @@ static INLINE void err_sys(const char* msg) { printf("wolfSSH error: %s\n", msg); } +#elif defined(WOLFSSH_ZEPHYR) +static INLINE void err_sys(const char* msg) +{ + printf("wolfSSH error: %s errno: %d\n", msg, errno); + exit(EXIT_FAILURE); +} #else static INLINE WS_NORETURN void err_sys(const char* msg) { @@ -397,7 +434,21 @@ static INLINE void build_addr(SOCKADDR_IN_T* addr, const char* peer, #ifndef TEST_IPV6 /* peer could be in human readable form */ - if ( ((size_t)peer != INADDR_ANY) && isalpha((int)peer[0])) { + if ( ((size_t)peer != INADDR_ANY) && isalnum((int)peer[0])) { + #ifdef WOLFSSH_ZEPHYR + struct zsock_addrinfo hints, *addrInfo; + char portStr[6]; + XSNPRINTF(portStr, sizeof(portStr), "%d", port); + XMEMSET(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + if (getaddrinfo((char*)peer, portStr, &hints, &addrInfo) == 0) { + XMEMCPY(addr, addrInfo->ai_addr, sizeof(*addr)); + freeaddrinfo(addrInfo); + useLookup = 1; + } + #else #ifdef CYASSL_MDK_ARM int err; struct hostent* entry = gethostbyname(peer, &err); @@ -408,6 +459,7 @@ static INLINE void build_addr(SOCKADDR_IN_T* addr, const char* peer, NU_HOSTENT h; entry = &h; NU_Get_Host_By_Name((char*)peer, entry); + #elif defined(WOLFSSH_ZEPHYR) #else struct hostent* entry = gethostbyname(peer); #endif @@ -424,6 +476,7 @@ static INLINE void build_addr(SOCKADDR_IN_T* addr, const char* peer, } else err_sys("no entry for host"); + #endif } #endif @@ -499,6 +552,8 @@ static INLINE void tcp_socket(WS_SOCKET_T* sockFd) *sockFd = 0; #elif defined(MICROCHIP_TCPIP) *sockFd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); +#elif defined(WOLFSSH_ZEPHYR) + *sockFd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); #elif defined(WOLFSSL_NUCLEUS) *sockFd = NU_Socket(NU_FAMILY_IP, NU_TYPE_STREAM, 0); #else @@ -530,6 +585,8 @@ static INLINE void tcp_socket(WS_SOCKET_T* sockFd) /* nothing to define */ #elif defined(WOLFSSL_ESPIDF) /* nothing to define */ +#elif defined(WOLFSSL_ZEPHYR) + /* nothing to define */ #else /* no S_NOSIGPIPE */ signal(SIGPIPE, SIG_IGN); #endif /* S_NOSIGPIPE */ @@ -581,9 +638,10 @@ static INLINE void tcp_listen(WS_SOCKET_T* sockfd, word16* port, int useAnyAddr) build_addr(&addr, (useAnyAddr ? INADDR_ANY : wolfSshIp), *port); tcp_socket(sockfd); -#if !defined(USE_WINDOWS_API) && !defined(WOLFSSL_MDK_ARM)\ - && !defined(WOLFSSL_KEIL_TCP_NET)\ - && !defined(WOLFSSL_NUCLEUS) +#if !defined(USE_WINDOWS_API) && !defined(WOLFSSL_MDK_ARM) \ + && !defined(WOLFSSL_KEIL_TCP_NET) \ + && !defined(WOLFSSL_NUCLEUS) \ + && !defined(WOLFSSH_ZEPHYR) { int res; #ifdef MICROCHIP_TCPIP @@ -844,6 +902,7 @@ static INLINE void WaitTcpReady(func_args* args) #define WOLFSSL_V5_5_1 0x05005001 #if (LIBWOLFSSL_VERSION_HEX < WOLFSSL_V5_5_1) && !defined(WOLFSSL_THREAD) + #define WOLFSSH_OLD_THREADING #ifdef SINGLE_THREADED typedef unsigned int THREAD_RETURN; typedef void* THREAD_TYPE; @@ -871,6 +930,27 @@ static INLINE void WaitTcpReady(func_args* args) #ifdef WOLFSSH_TEST_THREADING + +#ifndef WOLFSSH_OLD_THREADING + +static INLINE void ThreadStart(THREAD_CB fun, void* args, THREAD_TYPE* thread) +{ + (void)wolfSSL_NewThread(thread, fun, args); +} + +static INLINE void ThreadJoin(THREAD_TYPE thread) +{ + (void)wolfSSL_JoinThread(thread); +} + +#ifdef WOLFSSL_THREAD_NO_JOIN +static INLINE void ThreadStartNoJoin(THREAD_CB fun, void* args) +{ + (void)wolfSSL_NewThreadNoJoin(fun, args); +} +#endif + +#else typedef THREAD_RETURN (WOLFSSH_THREAD *THREAD_FUNC)(void*); @@ -969,6 +1049,15 @@ static INLINE void ThreadDetach(THREAD_TYPE thread) #endif } +static INLINE void ThreadStartNoJoin(THREAD_FUNC fun, void* args) +{ + THREAD_TYPE thread; + ThreadStart(fun, args, &thread); + ThreadDetach(thread); +} + +#endif /* WOLFSSH_OLD_THREADING */ + #endif /* WOLFSSH_TEST_THREADING */ #ifdef TEST_IPV6 diff --git a/wolfssh/wolfscp.h b/wolfssh/wolfscp.h index de57895d9..fedf57719 100644 --- a/wolfssh/wolfscp.h +++ b/wolfssh/wolfscp.h @@ -83,6 +83,9 @@ enum WS_ScpFileStates { #elif defined(USE_WINDOWS_API) char* entry; WIN32_FILE_ATTRIBUTE_DATA s; + #elif defined(WOLFSSH_ZEPHYR) + struct fs_dirent entry; + WSTAT_T s; /* stat info from file */ #else struct dirent* entry; /* file entry, from readdir() */ struct stat s; /* stat info from file */ diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt new file mode 100644 index 000000000..accf3ffa1 --- /dev/null +++ b/zephyr/CMakeLists.txt @@ -0,0 +1,13 @@ +if(CONFIG_WOLFSSH) + zephyr_include_directories(${ZEPHYR_CURRENT_MODULE_DIR}) + zephyr_include_directories(${ZEPHYR_CURRENT_MODULE_DIR}/zephyr) + zephyr_library_include_directories(${ZEPHYR_CURRENT_MODULE_DIR}) + FILE(GLOB wolfssh_sources ${ZEPHYR_CURRENT_MODULE_DIR}/src/*.c) + target_sources(app PRIVATE ${wolfssh_sources}) + if(CONFIG_WOLFSSH_DEBUG) + target_compile_definitions(app PUBLIC DEBUG_WOLFSSH) + endif() + target_compile_definitions(app PUBLIC WOLFSSH_ZEPHYR) + target_compile_definitions(app PUBLIC WOLFSSH_IGNORE_FILE_WARN) + target_compile_definitions(app PUBLIC WOLFSSH_NO_TIMESTAMP) +endif() diff --git a/zephyr/Kconfig b/zephyr/Kconfig new file mode 100644 index 000000000..7148506e0 --- /dev/null +++ b/zephyr/Kconfig @@ -0,0 +1,25 @@ +menuconfig WOLFSSH + bool "wolfSSH module support" + select WOLFSSL + +if WOLFSSH +config WOLFSSH_SETTINGS_FILE + string "wolfSSH settings file" + help + Use a specific wolfSSH settings file. + +config WOLFSSH_SFTP_DEFAULT_DIR + string "wolfSSH sftp default directory" + help + Use a specific directory as the default wolfSSH sftp working directory. + +config WOLFSSH_DEBUG + bool "wolfSSH debug activation" + help + Enable debugging activation for wolfSSH. + +config ZEPHYR_WOLFSSH_MODULE + bool + depends on WOLFSSH +endif + diff --git a/zephyr/README.md b/zephyr/README.md new file mode 100644 index 000000000..41c5ca395 --- /dev/null +++ b/zephyr/README.md @@ -0,0 +1,69 @@ +Zephyr Project Port +=================== + +## Overview + +This port is for the Zephyr RTOS Project, available [here](https://www.zephyrproject.org/). + + +It provides the following zephyr code. + +- modules/lib/wolfssh + - wolfSSH library code +- modules/lib/wolfssh/zephyr/ + - Configuration and CMake files for wolfSSH as a Zephyr module +- modules/lib/wolfssh/zephyr/samples/tests + - wolfSSH tests + +## How to setup as a Zephyr Module + +Follow the [instructions](https://docs.zephyrproject.org/latest/develop/getting_started/index.html) to setup a zephyr project. + +### Modify your project's west manifest + +Add wolfSSH as a project to your west.yml: + +``` +manifest: + remotes: + # + - name: wolfssh + url-base: https://github.com/wolfssl + + projects: + # + - name: wolfssh + path: modules/lib/wolfssh + revision: master + remote: wolfssh +``` + +Update west's modules: + +```bash +west update +``` + +Now west recognizes 'wolfssh' as a module, and will include it's Kconfig and +CMakeFiles.txt in the build system. + +## Build and Run Samples + +If you want to run build apps without running `west zephyr-export` then it is +possible by setting the `CMAKE_PREFIX_PATH` variable to the location of the +zephyr sdk and building from the `zephyr` directory. For example: + +``` +CMAKE_PREFIX_PATH=/path/to/zephyr-sdk- west build -p always -b qemu_x86 ../modules/lib/wolfssh/zephyr/samples/tests/ +``` + +### Build and Run Tests + +build and execute `tests` + +```bash +cd [zephyrproject] +west build -p auto -b qemu_x86 modules/lib/wolfssh/zephyr/samples/tests +west build -t run +``` + diff --git a/zephyr/module.yml b/zephyr/module.yml new file mode 100644 index 000000000..5b7e4a718 --- /dev/null +++ b/zephyr/module.yml @@ -0,0 +1,6 @@ +name: wolfssh +build: + cmake: zephyr + kconfig: zephyr/Kconfig + depends: + - wolfssl diff --git a/zephyr/samples/tests/CMakeLists.txt b/zephyr/samples/tests/CMakeLists.txt new file mode 100644 index 000000000..4f563b495 --- /dev/null +++ b/zephyr/samples/tests/CMakeLists.txt @@ -0,0 +1,11 @@ +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(wolfssl_tests) + +FILE(GLOB app_sources ../../../tests/*.c ../../../examples/client/client.c + ../../../examples/client/common.c ../../../examples/echoserver/echoserver.c + ../../../examples/sftpclient/sftpclient.c tests.c) +target_sources(app PRIVATE ${app_sources}) +add_definitions(-DWOLFSSL_ZEPHYR) +add_definitions(-DWOLFSSL_USER_SETTINGS) diff --git a/zephyr/samples/tests/prj.conf b/zephyr/samples/tests/prj.conf new file mode 100644 index 000000000..8bdd3f29b --- /dev/null +++ b/zephyr/samples/tests/prj.conf @@ -0,0 +1,78 @@ +# Kernel options +CONFIG_MAIN_STACK_SIZE=32768 +CONFIG_ENTROPY_GENERATOR=y +CONFIG_INIT_STACKS=y +CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=131072 + +# Enable wolfSSH +CONFIG_WOLFSSH=y +CONFIG_WOLFSSH_SETTINGS_FILE="samples/tests/user_settings.h" +CONFIG_WOLFSSH_SFTP_DEFAULT_DIR="/RAM:" + +# Pthreads +CONFIG_PTHREAD_IPC=y + +# Clock for time() +CONFIG_POSIX_CLOCK=y + +# Networking +CONFIG_NETWORKING=y +CONFIG_NET_TEST=y +CONFIG_NET_IPV4=y +CONFIG_NET_IPV6=n +CONFIG_NET_TCP=y +CONFIG_NET_SOCKETS=y +CONFIG_NET_SOCKETS_POSIX_NAMES=y + +CONFIG_NET_TEST=y +CONFIG_NET_LOOPBACK=y + +# Network driver config +CONFIG_TEST_RANDOM_GENERATOR=y + +# Network address config +CONFIG_NET_CONFIG_SETTINGS=y +CONFIG_NET_CONFIG_NEED_IPV4=y +CONFIG_NET_CONFIG_MY_IPV4_ADDR="192.0.2.1" +CONFIG_NET_CONFIG_PEER_IPV4_ADDR="192.0.2.2" +CONFIG_NET_CONFIG_MY_IPV4_GW="192.0.2.2" + +CONFIG_NET_PKT_TX_COUNT=10 + +# Logging +CONFIG_PRINTK=y +CONFIG_LOG=y +CONFIG_LOG_MODE_IMMEDIATE=y +#CONFIG_WOLFSSH_DEBUG=y +#CONFIG_WOLFSSL_DEBUG=y +#CONFIG_DEBUG=y + +# Enable logging using RTT and UART +#CONFIG_CBPRINTF_LIBC_SUBSTS=y +#CONFIG_CBPRINTF_FP_SUPPORT=y +#CONFIG_CONSOLE=y +#CONFIG_LOG_BACKEND_UART=y +#CONFIG_LOG_BUFFER_SIZE=15360 + +# TLS configuration +CONFIG_WOLFSSL=y +CONFIG_WOLFSSL_BUILTIN=y +CONFIG_WOLFSSL_SETTINGS_FILE="samples/tests/wolfssl_user_settings.h" + +CONFIG_WOLFSSL_TLS_VERSION_1_2=y +CONFIG_WOLFSSL_KEY_EXCHANGE_ALL_ENABLED=y +CONFIG_WOLFSSL_CIPHER_ALL_ENABLED=y +CONFIG_WOLFSSL_MAC_ALL_ENABLED=y +CONFIG_WOLFSSL_HMAC_DRBG_ENABLED=y + +# FS +CONFIG_DISK_ACCESS=y +CONFIG_DISK_DRIVERS=y +CONFIG_DISK_DRIVER_RAM=y +CONFIG_DISK_RAM_VOLUME_SIZE=64 +CONFIG_FILE_SYSTEM=y +CONFIG_FILE_SYSTEM_MKFS=y +CONFIG_FAT_FILESYSTEM_ELM=y +CONFIG_FS_FATFS_LFN=y +CONFIG_FS_FATFS_LFN_MODE_STACK=y + diff --git a/zephyr/samples/tests/sample.yaml b/zephyr/samples/tests/sample.yaml new file mode 100644 index 000000000..f216d6345 --- /dev/null +++ b/zephyr/samples/tests/sample.yaml @@ -0,0 +1,15 @@ +sample: + description: wolfSSH tests + name: wolfSSH tests +common: + harness: console + harness_config: + type: one_line + regex: + - "Zephyr wolfSSH tests passed" +tests: + sample.lib.wolfssh_tests: + timeout: 50 + platform_allow: qemu_x86 + integration_platforms: + - qemu_x86 diff --git a/zephyr/samples/tests/tests.c b/zephyr/samples/tests/tests.c new file mode 100644 index 000000000..2f57aa092 --- /dev/null +++ b/zephyr/samples/tests/tests.c @@ -0,0 +1,100 @@ +/* tests.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 + + +#ifdef WOLFSSL_USER_SETTINGS + #include +#else + #include +#endif + +/* tests/unit.h collides with the wolfSSL header so use relative include */ +#include "../../../tests/unit.h" +#include "../../../tests/testsuite.h" +#include "../../../tests/api.h" +#include "../../../tests/sftp.h" +#include +#include +#include +#include +#include +#include + + +#ifndef CONFIG_FAT_FILESYSTEM_ELM +#error "This test is designed for FAT FS" +#endif + +#define CHECK_TEST_RETURN(func) do { \ + printf("\tRunning %s... ", #func); \ + ret = (func); \ + if (ret != 0) { \ + printf("failed with %d\n", ret); \ + goto exit_main; \ + } \ + printf("ok\n"); \ +} while(0) + + +int main(void) +{ + int ret = 0; + static FATFS fat_fs; + static struct fs_mount_t mnt_point = { + .type = FS_FATFS, + .mnt_point = CONFIG_WOLFSSH_SFTP_DEFAULT_DIR, + .fs_data = &fat_fs, + }; + struct fs_file_t zfp; + char file_contents[5]; + int i; + char filename[50]; + + WMEMSET(file_contents, 0xFE, sizeof(file_contents)); + + /* +1 because the default dir mount point starts with a / and we want to + * remove it when formatting */ + CHECK_TEST_RETURN(fs_mkfs(FS_FATFS, + (uintptr_t)(CONFIG_WOLFSSH_SFTP_DEFAULT_DIR+1), NULL, 0)); + CHECK_TEST_RETURN(fs_mount(&mnt_point)); + /* Setup the necessary files for the sftp tests */ + fs_file_t_init(&zfp); + snprintf(filename, sizeof(filename), "%s/%s", + CONFIG_WOLFSSH_SFTP_DEFAULT_DIR, "configure"); + CHECK_TEST_RETURN(fs_open(&zfp, filename, FS_O_WRITE|FS_O_CREATE)); + /* Write some random data to file */ + for (i = 0; i < 10; i++) + CHECK_TEST_RETURN(fs_write(&zfp, file_contents, sizeof(file_contents)) + < 0); + + CHECK_TEST_RETURN(fs_close(&zfp)); + + CHECK_TEST_RETURN(wolfSSH_UnitTest(0, NULL)); + CHECK_TEST_RETURN(wolfSSH_TestsuiteTest(0, NULL)); + CHECK_TEST_RETURN(wolfSSH_ApiTest(0, NULL)); + printf("Zephyr wolfSSH tests passed\n"); + +exit_main: + return ret; +} diff --git a/zephyr/samples/tests/user_settings.h b/zephyr/samples/tests/user_settings.h new file mode 100644 index 000000000..0f755a549 --- /dev/null +++ b/zephyr/samples/tests/user_settings.h @@ -0,0 +1,68 @@ +/* user_settings.h + * + * Copyright (C) 2014-2023 wolfSSL Inc. + * + * This file is part of wolfSSH. + * + * wolfSSH is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * wolfSSH is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with wolfSSH. If not, see . + */ + +#ifndef WOLFSSH_USER_SETTINGS_H +#define WOLFSSH_USER_SETTINGS_H + + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#undef WOLFSSH_SFTP +#define WOLFSSH_SFTP + +#undef WOLFSSH_SCP +#define WOLFSSH_SCP + +#undef NO_APITEST_MAIN_DRIVER +#define NO_APITEST_MAIN_DRIVER + +#undef NO_TESTSUITE_MAIN_DRIVER +#define NO_TESTSUITE_MAIN_DRIVER + +#undef NO_UNITTEST_MAIN_DRIVER +#define NO_UNITTEST_MAIN_DRIVER + +#undef NO_MAIN_DRIVER +#define NO_MAIN_DRIVER + +#undef WS_NO_SIGNAL +#define WS_NO_SIGNAL + +#undef WS_USE_TEST_BUFFERS +#define WS_USE_TEST_BUFFERS + +#undef NO_WOLFSSL_DIR +#define NO_WOLFSSL_DIR + +#undef WOLFSSH_NO_NONBLOCKING +#define WOLFSSH_NO_NONBLOCKING + +#define DEFAULT_WINDOW_SZ (128 * 128) +#define WOLFSSH_MAX_SFTP_RW 8192 + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/zephyr/samples/tests/wolfssl_user_settings.h b/zephyr/samples/tests/wolfssl_user_settings.h new file mode 100644 index 000000000..35cd345f6 --- /dev/null +++ b/zephyr/samples/tests/wolfssl_user_settings.h @@ -0,0 +1,134 @@ +/* wolfssl_user_settings.h + * + * Copyright (C) 2014-2023 wolfSSL Inc. + * + * This file is part of wolfSSH. + * + * wolfSSH is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * wolfSSH is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with wolfSSH. If not, see . + */ + +#ifndef WOLFSSL_USER_SETTINGS_H +#define WOLFSSL_USER_SETTINGS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#undef WOLFSSL_ZEPHYR +#define WOLFSSL_ZEPHYR + +#undef TFM_TIMING_RESISTANT +#define TFM_TIMING_RESISTANT + +#undef ECC_TIMING_RESISTANT +#define ECC_TIMING_RESISTANT + +#undef WC_RSA_BLINDING +#define WC_RSA_BLINDING + +#undef HAVE_AESGCM +#define HAVE_AESGCM + +#undef WOLFSSL_SHA512 +#define WOLFSSL_SHA512 + +#undef WOLFSSL_SHA384 +#define WOLFSSL_SHA384 + +#undef NO_DSA +#define NO_DSA + +#undef HAVE_ECC +#define HAVE_ECC + +#undef TFM_ECC256 +#define TFM_ECC256 + +#undef WOLFSSL_BASE64_ENCODE +#define WOLFSSL_BASE64_ENCODE + +#undef NO_RC4 +#define NO_RC4 + +#undef WOLFSSL_SHA224 +#define WOLFSSL_SHA224 + +#undef WOLFSSL_SHA3 +#define WOLFSSL_SHA3 + +#undef HAVE_POLY1305 +#define HAVE_POLY1305 + +#undef HAVE_ONE_TIME_AUTH +#define HAVE_ONE_TIME_AUTH + +#undef HAVE_CHACHA +#define HAVE_CHACHA + +#undef HAVE_HASHDRBG +#define HAVE_HASHDRBG + +#undef HAVE_TLS_EXTENSIONS +#define HAVE_TLS_EXTENSIONS + +#undef HAVE_SUPPORTED_CURVES +#define HAVE_SUPPORTED_CURVES + +#undef HAVE_EXTENDED_MASTER +#define HAVE_EXTENDED_MASTER + +#undef NO_PSK +#define NO_PSK + +#undef NO_MD4 +#define NO_MD4 + +#undef NO_PWDBASED +#define NO_PWDBASED + +#undef USE_FAST_MATH +#define USE_FAST_MATH + +#undef WOLFSSL_NO_ASM +#define WOLFSSL_NO_ASM + +#undef WOLFSSL_X86_BUILD +#define WOLFSSL_X86_BUILD + +#undef WC_NO_ASYNC_THREADING +#define WC_NO_ASYNC_THREADING + +#undef NO_DES3 +#define NO_DES3 + +#undef WOLFSSL_STATIC_MEMORY +#define WOLFSSL_STATIC_MEMORY + +#undef WOLFSSL_TLS13 +#define WOLFSSL_TLS13 + +#undef HAVE_HKDF +#define HAVE_HKDF + +#undef WC_RSA_PSS +#define WC_RSA_PSS + +#undef HAVE_FFDHE_2048 +#define HAVE_FFDHE_2048 + +#ifdef __cplusplus +} +#endif + +#endif /* WOLFSSL_USER_SETTINGS_H */