diff --git a/.github/workflows/async.yml b/.github/workflows/async.yml index 949e87dfd..84eb4c588 100644 --- a/.github/workflows/async.yml +++ b/.github/workflows/async.yml @@ -23,7 +23,7 @@ jobs: - name: Test wolfSSL async run: | - ./async-check.sh setup + ./async-check.sh install ./configure ${{ matrix.config }} make check diff --git a/.gitignore b/.gitignore index cb6d67e4b..3c526f6eb 100644 --- a/.gitignore +++ b/.gitignore @@ -10,7 +10,7 @@ ctaocrypt/src/src/ *.cache .dirstamp *.user -configure +configure config.* !cmake/config.in *Debug/ @@ -64,6 +64,8 @@ ctaocrypt/benchmark/benchmark ctaocrypt/test/testctaocrypt wolfcrypt/benchmark/benchmark wolfcrypt/test/testwolfcrypt +examples/async/async_client +examples/async/async_server examples/benchmark/tls_bench examples/client/client examples/echoclient/echoclient @@ -407,7 +409,7 @@ libFuzzer XXX-fips-test # ASYNC -async +/wolfAsyncCrypt # Generated user_settings_asm.h. user_settings_asm.h diff --git a/async-check.sh b/async-check.sh index 5a0246940..28599c471 100755 --- a/async-check.sh +++ b/async-check.sh @@ -1,34 +1,23 @@ #!/bin/bash -# async-check.sh - # This script creates symbolic links to the required asynchronous # file for using the asynchronous simulator and make check -# -# $ ./async-check [keep|clean|setup] -# -# - keep: (default off) ./async and links kept around for inspection -# - clean: (default off) only cleanup existing ./async and links -# - setup: (default off) only setup ./async and links but don't run config -# or make -# + +# Fail on any error in script +set -e ASYNC_REPO=https://github.com/wolfSSL/wolfAsyncCrypt.git +ASYNC_DIR=${ASYNC_DIR:-wolfAsyncCrypt} function Usage() { - printf '\n%s\n\n' "Usage: $0 [keep|clean|setup]" - printf '%s\n' "Where \"keep\" means keep (default off) async files around for inspection" - printf '%s\n' "Where \"clean\" means only clean (default off) the async files" - printf '%s\n\n' "Where \"setup\" means only setup (default off) the async files" - printf '%s\n' "EXAMPLE:" - printf '%s\n' "---------------------------------" - printf '%s\n' "./async-check.sh keep" - printf '%s\n' "./async-check.sh clean" - printf '%s\n' "./async-check.sh setup" - printf '%s\n\n' "---------------------------------" + printf "Usage: $0 [install|uninstall|test|remove]\n" + printf "\tinstall - get and set up links to wolfAsyncCrypt files\n" + printf "\tuninstall - remove the links to wolfAsyncCrypt\n" + printf "\ttest - install and run 'make check'\n" + printf "\tremove - uninstall and remove wolfAsyncCrypt\n" } -function CleanUp() { +function UnlinkFiles() { unlink ./wolfcrypt/src/async.c unlink ./wolfssl/wolfcrypt/async.h unlink ./wolfcrypt/src/port/intel/quickassist.c @@ -40,8 +29,6 @@ function CleanUp() { unlink ./wolfssl/wolfcrypt/port/cavium/cavium_nitrox.h unlink ./wolfcrypt/src/port/cavium/README.md - rm -rf ./async - # restore original README.md files git checkout -- wolfcrypt/src/port/cavium/README.md git checkout -- wolfcrypt/src/port/intel/README.md @@ -49,16 +36,46 @@ function CleanUp() { function LinkFiles() { # link files - ln -s -f ../../async/wolfcrypt/src/async.c ./wolfcrypt/src/async.c - ln -s -f ../../async/wolfssl/wolfcrypt/async.h ./wolfssl/wolfcrypt/async.h - ln -s -f ../../../../async/wolfcrypt/src/port/intel/quickassist.c ./wolfcrypt/src/port/intel/quickassist.c - ln -s -f ../../../../async/wolfcrypt/src/port/intel/quickassist_mem.c ./wolfcrypt/src/port/intel/quickassist_mem.c - ln -s -f ../../../../async/wolfcrypt/src/port/intel/README.md ./wolfcrypt/src/port/intel/README.md - ln -s -f ../../../../async/wolfssl/wolfcrypt/port/intel/quickassist.h ./wolfssl/wolfcrypt/port/intel/quickassist.h - ln -s -f ../../../../async/wolfssl/wolfcrypt/port/intel/quickassist_mem.h ./wolfssl/wolfcrypt/port/intel/quickassist_mem.h - ln -s -f ../../../../async/wolfcrypt/src/port/cavium/cavium_nitrox.c ./wolfcrypt/src/port/cavium/cavium_nitrox.c - ln -s -f ../../../../async/wolfssl/wolfcrypt/port/cavium/cavium_nitrox.h ./wolfssl/wolfcrypt/port/cavium/cavium_nitrox.h - ln -s -f ../../../../async/wolfcrypt/src/port/cavium/README.md ./wolfcrypt/src/port/cavium/README.md + ln -s -f ../../${ASYNC_DIR}/wolfcrypt/src/async.c ./wolfcrypt/src/async.c + ln -s -f ../../${ASYNC_DIR}/wolfssl/wolfcrypt/async.h ./wolfssl/wolfcrypt/async.h + ln -s -f ../../../../${ASYNC_DIR}/wolfcrypt/src/port/intel/quickassist.c ./wolfcrypt/src/port/intel/quickassist.c + ln -s -f ../../../../${ASYNC_DIR}/wolfcrypt/src/port/intel/quickassist_mem.c ./wolfcrypt/src/port/intel/quickassist_mem.c + ln -s -f ../../../../${ASYNC_DIR}/wolfcrypt/src/port/intel/README.md ./wolfcrypt/src/port/intel/README.md + ln -s -f ../../../../${ASYNC_DIR}/wolfssl/wolfcrypt/port/intel/quickassist.h ./wolfssl/wolfcrypt/port/intel/quickassist.h + ln -s -f ../../../../${ASYNC_DIR}/wolfssl/wolfcrypt/port/intel/quickassist_mem.h ./wolfssl/wolfcrypt/port/intel/quickassist_mem.h + ln -s -f ../../../../${ASYNC_DIR}/wolfcrypt/src/port/cavium/cavium_nitrox.c ./wolfcrypt/src/port/cavium/cavium_nitrox.c + ln -s -f ../../../../${ASYNC_DIR}/wolfssl/wolfcrypt/port/cavium/cavium_nitrox.h ./wolfssl/wolfcrypt/port/cavium/cavium_nitrox.h + ln -s -f ../../../../${ASYNC_DIR}/wolfcrypt/src/port/cavium/README.md ./wolfcrypt/src/port/cavium/README.md +} + +function Install() { + if [ -d $ASYNC_DIR ]; + then + echo "Using existing async repo" + else + # make a clone of the wolfAsyncCrypt repository + git clone --depth 1 $ASYNC_REPO $ASYNC_DIR + fi + +# setup auto-conf + ./autogen.sh + LinkFiles +} + +function Uninstall() { + UnlinkFiles +} + +function Test() { + Install + ./configure --enable-asynccrypt --enable-all + make check +} + +function Remove() { + UnlinkFiles + + rm -rf ./async } if [ "$#" -gt 1 ]; then @@ -66,19 +83,18 @@ if [ "$#" -gt 1 ]; then exit 1 fi -KEEP=no -ONLY_SETUP=no - case "x$1" in - "xkeep") - KEEP=yes + "xinstall") + Install ;; - "xclean") - CleanUp - exit 0 + "xuninstall") + Uninstall ;; - "xsetup") - ONLY_SETUP=yes + "xremove") + Remove + ;; + "xtest") + Test ;; *) Usage @@ -86,28 +102,3 @@ case "x$1" in ;; esac -# Fail on any error in script from now on -set -e - -if [ -d ./async ]; -then - echo "Using existing async repo" -else - # make a clone of the wolfAsyncCrypt repository - git clone --depth 1 $ASYNC_REPO async -fi - -# setup auto-conf -./autogen.sh -LinkFiles -if [ "x$ONLY_SETUP" == "xno" ]; -then - ./configure --enable-asynccrypt --enable-all - make check - # Clean up - if [ "x$KEEP" == "xno" ]; - then - CleanUp - fi -fi - diff --git a/examples/async/README.md b/examples/async/README.md new file mode 100644 index 000000000..2dbde6c40 --- /dev/null +++ b/examples/async/README.md @@ -0,0 +1,34 @@ +# wolfSSL Asynchronous Cryptography support + +Supported with: +* Intel QuickAssist +* Marvell (Cavium) Nitrox +* Crypto Callbacks (`--enable-cryptocb`) +* PK Callbacks (`--enable-pkcallbacks`) + +Requires files from https://github.com/wolfSSL/wolfAsyncCrypt +See `async-check.sh` for how to setup. + +Tested with: +* `./configure --enable-asynccrypt --enable-rsa --disable-ecc` +* `./configure --enable-asynccrypt --disable-rsa --enable-ecc` +* `./configure --enable-asynccrypt --enable-cryptocb --enable-rsa --disable-ecc` +* `./configure --enable-asynccrypt --enable-cryptocb --disable-rsa --enable-ecc` +* `./configure --enable-asynccrypt --enable-pkcallbacks --enable-rsa --disable-ecc` +* `./configure --enable-asynccrypt --enable-pkcallbacks --disable-rsa --enable-ecc` + +``` +make +./examples/async/async_server +./examples/async/async_client 127.0.0.1 +``` + +## Asynchronous Cryptography Design + +When a cryptogaphic call is handed off to harware it return `WC_PENDING_E` up to caller. Then it can keep calling until the operation completes. For some platforms it is required to call `wolfSSL_AsyncPoll`. At the TLS layer a "devId" (Device ID) must be set using `wolfSSL_CTX_SetDevId` to indicate desire to offload cryptography. + +For further design details please see: https://github.com/wolfSSL/wolfAsyncCrypt#design + +## Support + +For questions please email support@wolfssl.com diff --git a/examples/async/async_client.c b/examples/async/async_client.c new file mode 100644 index 000000000..a0df6a146 --- /dev/null +++ b/examples/async/async_client.c @@ -0,0 +1,277 @@ +/* async_client.c + * + * Copyright (C) 2006-2023 wolfSSL Inc. + * + * This file is part of wolfSSL. (formerly known as CyaSSL) + * + * 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-1301, USA + */ + +/* TLS client demonstrating asynchronous cryptography features and optionally + * using the crypto or PK callbacks */ + +/* std */ +#include +#include +#include + +/* socket */ +#include +#include +#include +#include + +/* wolfSSL */ +#ifndef WOLFSSL_USER_SETTINGS + #include +#endif +#include +#include +#include +#include "examples/async/async_tls.h" + +/* Test certificates and keys for RSA and ECC */ +#ifndef NO_RSA + #define CERT_FILE "./certs/client-cert.pem" + #define KEY_FILE "./certs/client-key.pem" + #define CA_FILE "./certs/ca-cert.pem" +#elif defined(HAVE_ECC) + #define CERT_FILE "./certs/client-ecc-cert.pem" + #define KEY_FILE "./certs/ecc-client-key.pem" + #define CA_FILE "./certs/ca-ecc-cert.pem" +#else + #error No authentication algorithm (ECC/RSA) +#endif + +int client_async_test(int argc, char** argv) +{ + int ret = 0; + int sockfd = SOCKET_INVALID; + struct sockaddr_in servAddr; + char buff[TEST_BUF_SZ]; + size_t len; + int devId = 1; /* anything besides -2 (INVALID_DEVID) */ +#ifdef WOLF_CRYPTO_CB + AsyncTlsCryptoCbCtx myCtx; +#endif + int err; + char errBuff[WOLFSSL_MAX_ERROR_SZ]; + + /* declare wolfSSL objects */ + WOLFSSL_CTX* ctx = NULL; + WOLFSSL* ssl = NULL; + + /* Check for proper calling convention */ + if (argc != 2) { + printf("usage: %s \n", argv[0]); + return 0; + } + + /* Create a socket that uses an internet IPv4 address, + * Sets the socket to be stream based (TCP), + * 0 means choose the default protocol. */ + if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { + fprintf(stderr, "ERROR: failed to create the socket\n"); + ret = -1; goto exit; + } + + /* Initialize the server address struct with zeros */ + memset(&servAddr, 0, sizeof(servAddr)); + + /* Fill in the server address */ + servAddr.sin_family = AF_INET; /* using IPv4 */ + servAddr.sin_port = htons(DEFAULT_PORT); /* on DEFAULT_PORT */ + + /* Get the server IPv4 address from the command line call */ + if (inet_pton(AF_INET, argv[1], &servAddr.sin_addr) != 1) { + fprintf(stderr, "ERROR: invalid address\n"); + ret = -1; goto exit; + } + + /* Connect to the server */ + if ((ret = connect(sockfd, (struct sockaddr*) &servAddr, sizeof(servAddr))) + == -1) { + fprintf(stderr, "ERROR: failed to connect\n"); + goto exit; + } + + /*---------------------------------*/ + /* Start of wolfSSL initialization and configuration */ + /*---------------------------------*/ +#ifdef DEBUG_WOLFSSL + wolfSSL_Debugging_ON(); +#endif + + /* Initialize wolfSSL */ + if ((ret = wolfSSL_Init()) != WOLFSSL_SUCCESS) { + fprintf(stderr, "ERROR: Failed to initialize the library\n"); + goto exit; + } + + /* Create and initialize WOLFSSL_CTX */ + if ((ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())) == NULL) { + fprintf(stderr, "ERROR: failed to create WOLFSSL_CTX\n"); + ret = -1; goto exit; + } + +#ifdef WOLF_CRYPTO_CB + XMEMSET(&myCtx, 0, sizeof(myCtx)); + /* register a devID for crypto callbacks */ + ret = wc_CryptoCb_RegisterDevice(devId, AsyncTlsCryptoCb, &myCtx); + if (ret != 0) { + fprintf(stderr, "wc_CryptoCb_RegisterDevice: error %d", ret); + goto exit; + } +#endif + /* register a devID for crypto callbacks */ + wolfSSL_CTX_SetDevId(ctx, devId); + + /* Load client certificate into WOLFSSL_CTX */ + if ((ret = wolfSSL_CTX_use_certificate_file(ctx, CERT_FILE, WOLFSSL_FILETYPE_PEM)) + != WOLFSSL_SUCCESS) { + fprintf(stderr, "ERROR: failed to load %s, please check the file.\n", + CERT_FILE); + goto exit; + } + + /* Load client key into WOLFSSL_CTX */ + if ((ret = wolfSSL_CTX_use_PrivateKey_file(ctx, KEY_FILE, WOLFSSL_FILETYPE_PEM)) + != WOLFSSL_SUCCESS) { + fprintf(stderr, "ERROR: failed to load %s, please check the file.\n", + KEY_FILE); + goto exit; + } + + /* Load CA certificate into WOLFSSL_CTX */ + if ((ret = wolfSSL_CTX_load_verify_locations(ctx, CA_FILE, NULL)) + != WOLFSSL_SUCCESS) { + fprintf(stderr, "ERROR: failed to load %s, please check the file.\n", + CA_FILE); + goto exit; + } + + /* Create a WOLFSSL object */ + if ((ssl = wolfSSL_new(ctx)) == NULL) { + fprintf(stderr, "ERROR: failed to create WOLFSSL object\n"); + ret = -1; goto exit; + } + + /* Attach wolfSSL to the socket */ + if ((ret = wolfSSL_set_fd(ssl, sockfd)) != WOLFSSL_SUCCESS) { + fprintf(stderr, "ERROR: Failed to set the file descriptor\n"); + goto exit; + } + + /* Connect to wolfSSL on the server side */ +#ifdef WOLFSSL_ASYNC_CRYPT + err = 0; /* Reset error */ +#endif + do { + #ifdef WOLFSSL_ASYNC_CRYPT + if (err == WC_PENDING_E) { + ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + if (ret < 0) + break; + } + #endif + ret = wolfSSL_connect(ssl); + err = wolfSSL_get_error(ssl, 0); + } while (err == WC_PENDING_E); + if (ret != WOLFSSL_SUCCESS) { + fprintf(stderr, "wolfSSL_connect error %d: %s\n", + err, wolfSSL_ERR_error_string(err, errBuff)); + goto exit; + } + + /* Get a message for the server from stdin */ + printf("Message for server: "); + memset(buff, 0, sizeof(buff)); + if (fgets(buff, sizeof(buff), stdin) == NULL) { + fprintf(stderr, "ERROR: failed to get message for server\n"); + ret = -1; goto exit; + } + len = strnlen(buff, sizeof(buff)); + + /* Send the message to the server */ +#ifdef WOLFSSL_ASYNC_CRYPT + err = 0; /* Reset error */ +#endif + do { + #ifdef WOLFSSL_ASYNC_CRYPT + if (err == WC_PENDING_E) { + ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + if (ret < 0) + break; + } + #endif + ret = wolfSSL_write(ssl, buff, (int)len); + err = wolfSSL_get_error(ssl, 0); + } while (err == WC_PENDING_E); + if (ret != (int)len) { + fprintf(stderr, "wolfSSL_write error %d: %s\n", + err, wolfSSL_ERR_error_string(err, errBuff)); + goto exit; + } + + /* Read the server data into our buff array */ + memset(buff, 0, sizeof(buff)); +#ifdef WOLFSSL_ASYNC_CRYPT + err = 0; /* Reset error */ +#endif + do { + #ifdef WOLFSSL_ASYNC_CRYPT + if (err == WC_PENDING_E) { + ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + if (ret < 0) + break; + } + #endif + ret = wolfSSL_read(ssl, buff, sizeof(buff)-1); + err = wolfSSL_get_error(ssl, 0); + } while (err == WC_PENDING_E); + if (ret < 0) { + fprintf(stderr, "wolfSSL_read error %d: %s\n", + err, wolfSSL_ERR_error_string(err, errBuff)); + goto exit; + } + + /* Print to stdout any data the server sends */ + printf("Server: %s\n", buff); + + /* Return reporting a success */ + ret = 0; + +exit: + /* Cleanup and return */ + if (sockfd != SOCKET_INVALID) + close(sockfd); /* Close the connection to the server */ + if (ssl) + wolfSSL_free(ssl); /* Free the wolfSSL object */ + if (ctx) + wolfSSL_CTX_free(ctx); /* Free the wolfSSL context object */ + wolfSSL_Cleanup(); /* Cleanup the wolfSSL environment */ + + (void)argc; + (void)argv; + + return ret; +} + +#ifndef NO_MAIN_DRIVER +int main(int argc, char** argv) +{ + return client_async_test(argc, argv); +} +#endif /* !NO_MAIN_DRIVER */ diff --git a/examples/async/async_server.c b/examples/async/async_server.c new file mode 100644 index 000000000..41eaae86e --- /dev/null +++ b/examples/async/async_server.c @@ -0,0 +1,363 @@ +/* async_server.c + * + * Copyright (C) 2006-2023 wolfSSL Inc. + * + * This file is part of wolfSSL. (formerly known as CyaSSL) + * + * 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-1301, USA + */ + +/* TLS server demonstrating asynchronous cryptography features and optionally + * using the crypto or PK callbacks */ + +/* std */ +#include +#include +#include + +/* socket */ +#include +#include +#include +#include + +#define HAVE_SIGNAL +#ifdef HAVE_SIGNAL +#include /* for catching ctrl+c */ +#endif + +/* wolfSSL */ +#ifndef WOLFSSL_USER_SETTINGS + #include +#endif +#include +#include +#include +#include "examples/async/async_tls.h" + +/* Test certificates and keys for RSA and ECC */ +#ifndef NO_RSA + #define CERT_FILE "./certs/server-cert.pem" + #define KEY_FILE "./certs/server-key.pem" + #define CA_FILE "./certs/client-cert.pem" +#elif defined(HAVE_ECC) + #define CERT_FILE "./certs/server-ecc.pem" + #define KEY_FILE "./certs/ecc-key.pem" + #define CA_FILE "./certs/client-ecc-cert.pem" +#else + #error No authentication algorithm (ECC/RSA) +#endif + +static int mSockfd = SOCKET_INVALID; +static int mConnd = SOCKET_INVALID; +static int mShutdown = 0; + +#ifdef HAVE_SIGNAL +static void sig_handler(const int sig) +{ +#ifdef DEBUG_WOLFSSL + fprintf(stderr, "SIGINT handled = %d.\n", sig); +#else + (void)sig; +#endif + + mShutdown = 1; + if (mConnd != SOCKET_INVALID) { + close(mConnd); /* Close the connection to the client */ + mConnd = SOCKET_INVALID; + } + if (mSockfd != SOCKET_INVALID) { + close(mSockfd); /* Close the socket listening for clients */ + mSockfd = SOCKET_INVALID; + } +} +#endif + +int server_async_test(int argc, char** argv) +{ + int ret = 0; + struct sockaddr_in servAddr; + struct sockaddr_in clientAddr; + socklen_t size = sizeof(clientAddr); + char buff[TEST_BUF_SZ]; + size_t len; + const char* reply = "I hear ya fa shizzle!\n"; + int on; + int devId = 1; /* anything besides -2 (INVALID_DEVID) */ +#ifdef WOLF_CRYPTO_CB + AsyncTlsCryptoCbCtx myCtx; +#endif + int err; + char errBuff[WOLFSSL_MAX_ERROR_SZ]; + + /* declare wolfSSL objects */ + WOLFSSL_CTX* ctx = NULL; + WOLFSSL* ssl = NULL; + +#ifdef HAVE_SIGNAL + if ((signal(SIGINT, sig_handler)) == SIG_ERR) { + fprintf(stderr, "ERROR: failed to listen to SIGINT (errno: %d)\n",errno); + goto exit; + } +#endif + + /* Initialize the server address struct with zeros */ + memset(&servAddr, 0, sizeof(servAddr)); + + /* Fill in the server address */ + servAddr.sin_family = AF_INET; /* using IPv4 */ + servAddr.sin_port = htons(DEFAULT_PORT); /* on DEFAULT_PORT */ + servAddr.sin_addr.s_addr = INADDR_ANY; /* from anywhere */ + + + /* Create a socket that uses an internet IPv4 address, + * Sets the socket to be stream based (TCP), + * 0 means choose the default protocol. */ + if ((mSockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { + fprintf(stderr, "ERROR: failed to create the socket\n"); + goto exit; + } + + /* make sure server is setup for reuse addr/port */ + on = 1; + if (setsockopt(mSockfd, SOL_SOCKET, SO_REUSEADDR, + (char*)&on, (socklen_t)sizeof(on)) != 0) { + fprintf(stderr, "ERROR: failed to set SO_REUSEADDR (errno: %d)\n",errno); + goto exit; + } +#ifdef SO_REUSEPORT + if (setsockopt(mSockfd, SOL_SOCKET, SO_REUSEPORT, + (char*)&on, (socklen_t)sizeof(on)) != 0) { + fprintf(stderr, "ERROR: failed to set SO_REUSEPORT (errno: %d)\n",errno); + goto exit; + } +#endif + + /* Bind the server socket to our port */ + if (bind(mSockfd, (struct sockaddr*)&servAddr, sizeof(servAddr)) == -1) { + fprintf(stderr, "ERROR: failed to bind\n"); + goto exit; + } + + /* Listen for a new connection, allow 5 pending connections */ + if (listen(mSockfd, 5) == -1) { + fprintf(stderr, "ERROR: failed to listen\n"); + goto exit; + } + + /*---------------------------------*/ + /* Start of wolfSSL initialization and configuration */ + /*---------------------------------*/ +#ifdef DEBUG_WOLFSSL + wolfSSL_Debugging_ON(); +#endif + + /* Initialize wolfSSL */ + if ((ret = wolfSSL_Init()) != WOLFSSL_SUCCESS) { + fprintf(stderr, "ERROR: Failed to initialize the library\n"); + goto exit; + } + + /* Create and initialize WOLFSSL_CTX */ + if ((ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())) == NULL) { + fprintf(stderr, "ERROR: failed to create WOLFSSL_CTX\n"); + ret = -1; + goto exit; + } + +#ifdef WOLF_CRYPTO_CB + XMEMSET(&myCtx, 0, sizeof(myCtx)); + /* register a devID for crypto callbacks */ + ret = wc_CryptoCb_RegisterDevice(devId, AsyncTlsCryptoCb, &myCtx); + if (ret != 0) { + fprintf(stderr, "wc_CryptoCb_RegisterDevice: error %d", ret); + goto exit; + } +#endif + + /* register a devID for crypto callbacks */ + wolfSSL_CTX_SetDevId(ctx, devId); + + /* Require mutual authentication */ + wolfSSL_CTX_set_verify(ctx, + WOLFSSL_VERIFY_PEER | WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL); + + /* Load server certificates into WOLFSSL_CTX */ + if ((ret = wolfSSL_CTX_use_certificate_file(ctx, CERT_FILE, + WOLFSSL_FILETYPE_PEM)) != WOLFSSL_SUCCESS) { + fprintf(stderr, "ERROR: failed to load %s, please check the file.\n", + CERT_FILE); + goto exit; + } + + /* Load server key into WOLFSSL_CTX */ + if ((ret = wolfSSL_CTX_use_PrivateKey_file(ctx, KEY_FILE, + WOLFSSL_FILETYPE_PEM)) != WOLFSSL_SUCCESS) { + fprintf(stderr, "ERROR: failed to load %s, please check the file.\n", + KEY_FILE); + goto exit; + } + + /* Load client certificate as "trusted" into WOLFSSL_CTX */ + if ((ret = wolfSSL_CTX_load_verify_locations(ctx, CA_FILE, NULL)) + != WOLFSSL_SUCCESS) { + fprintf(stderr, "ERROR: failed to load %s, please check the file.\n", + CA_FILE); + goto exit; + } + + /* Continue to accept clients until mShutdown is issued */ + while (!mShutdown) { + printf("Waiting for a connection...\n"); + + /* Accept client connections */ + if ((mConnd = accept(mSockfd, (struct sockaddr*)&clientAddr, &size)) + == -1) { + fprintf(stderr, "ERROR: failed to accept the connection\n\n"); + ret = -1; goto exit; + } + + /* Create a WOLFSSL object */ + if ((ssl = wolfSSL_new(ctx)) == NULL) { + fprintf(stderr, "ERROR: failed to create WOLFSSL object\n"); + ret = -1; goto exit; + } + + /* Attach wolfSSL to the socket */ + wolfSSL_set_fd(ssl, mConnd); + + /* Establish TLS connection */ + #ifdef WOLFSSL_ASYNC_CRYPT + err = 0; /* Reset error */ + #endif + do { + #ifdef WOLFSSL_ASYNC_CRYPT + if (err == WC_PENDING_E) { + ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + if (ret < 0) + break; + } + #endif + ret = wolfSSL_accept(ssl); + err = wolfSSL_get_error(ssl, 0); + } while (err == WC_PENDING_E); + if (ret != WOLFSSL_SUCCESS) { + fprintf(stderr, "wolfSSL_accept error %d: %s\n", + err, wolfSSL_ERR_error_string(err, errBuff)); + goto exit; + } + + + printf("Client connected successfully\n"); + + /* Read the client data into our buff array */ + memset(buff, 0, sizeof(buff)); + #ifdef WOLFSSL_ASYNC_CRYPT + err = 0; /* Reset error */ + #endif + do { + #ifdef WOLFSSL_ASYNC_CRYPT + if (err == WC_PENDING_E) { + ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + if (ret < 0) + break; + } + #endif + ret = wolfSSL_read(ssl, buff, sizeof(buff)-1); + err = wolfSSL_get_error(ssl, 0); + } while (err == WC_PENDING_E); + if (ret < 0) { + fprintf(stderr, "wolfSSL_read error %d: %s\n", + err, wolfSSL_ERR_error_string(err, errBuff)); + goto exit; + } + + /* Print to stdout any data the client sends */ + printf("Client: %s\n", buff); + + /* Check for server shutdown command */ + if (strncmp(buff, "shutdown", 8) == 0) { + printf("Shutdown command issued!\n"); + mShutdown = 1; + } + + /* Write our reply into buff */ + memset(buff, 0, sizeof(buff)); + memcpy(buff, reply, strlen(reply)); + len = strnlen(buff, sizeof(buff)); + + /* Reply back to the client */ + #ifdef WOLFSSL_ASYNC_CRYPT + err = 0; /* Reset error */ + #endif + do { + #ifdef WOLFSSL_ASYNC_CRYPT + if (err == WC_PENDING_E) { + ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + if (ret < 0) + break; + } + #endif + ret = wolfSSL_write(ssl, buff, (int)len); + err = wolfSSL_get_error(ssl, 0); + } while (err == WC_PENDING_E); + if (ret != (int)len) { + fprintf(stderr, "wolfSSL_write error %d: %s\n", + err, wolfSSL_ERR_error_string(err, errBuff)); + goto exit; + } + + /* Cleanup after this connection */ + wolfSSL_shutdown(ssl); + if (ssl) { + wolfSSL_free(ssl); /* Free the wolfSSL object */ + ssl = NULL; + } + if (mConnd != SOCKET_INVALID) { + close(mConnd); /* Close the connection to the client */ + mConnd = SOCKET_INVALID; + } + } + + printf("Shutdown complete\n"); + +exit: + /* Cleanup and return */ + if (ssl) + wolfSSL_free(ssl); /* Free the wolfSSL object */ + if (mConnd != SOCKET_INVALID) { + close(mConnd); /* Close the connection to the client */ + mConnd = SOCKET_INVALID; + } + if (mSockfd != SOCKET_INVALID) { + close(mSockfd); /* Close the socket listening for clients */ + mSockfd = SOCKET_INVALID; + } + if (ctx) + wolfSSL_CTX_free(ctx); /* Free the wolfSSL context object */ + wolfSSL_Cleanup(); /* Cleanup the wolfSSL environment */ + + (void)argc; + (void)argv; + + return ret; +} + +#ifndef NO_MAIN_DRIVER +int main(int argc, char** argv) +{ + return server_async_test(argc, argv); +} +#endif /* !NO_MAIN_DRIVER */ diff --git a/examples/async/async_tls.c b/examples/async/async_tls.c new file mode 100644 index 000000000..1d4f68d53 --- /dev/null +++ b/examples/async/async_tls.c @@ -0,0 +1,158 @@ +/* async-tls.c + * + * Copyright (C) 2006-2023 wolfSSL Inc. + * + * This file is part of wolfSSL. (formerly known as CyaSSL) + * + * 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-1301, USA + */ + +#ifndef WOLFSSL_USER_SETTINGS +#include +#endif +#include +#include +#include +#include "examples/async/async_tls.h" + +/* ---------------------------------------------------------------------------*/ +/* --- Example Crypto Callback --- */ +/* ---------------------------------------------------------------------------*/ +#ifdef WOLF_CRYPTO_CB + +/* Example custom context for crypto callback */ +#ifndef TEST_PEND_COUNT +#define TEST_PEND_COUNT 2 +#endif + +/* Example crypto dev callback function that calls software version */ +/* This is where you would plug-in calls to your own hardware crypto */ +int AsyncTlsCryptoCb(int devIdArg, wc_CryptoInfo* info, void* ctx) +{ + int ret = CRYPTOCB_UNAVAILABLE; /* return this to bypass HW and use SW */ + AsyncTlsCryptoCbCtx* myCtx = (AsyncTlsCryptoCbCtx*)ctx; + + if (info == NULL) + return BAD_FUNC_ARG; + +#ifdef DEBUG_CRYPTOCB + wc_CryptoCb_InfoString(info); +#endif + + if (info->algo_type == WC_ALGO_TYPE_PK) { +#ifdef WOLFSSL_ASYNC_CRYPT + /* Test pending response */ + if (info->pk.type == WC_PK_TYPE_RSA || + info->pk.type == WC_PK_TYPE_EC_KEYGEN || + info->pk.type == WC_PK_TYPE_ECDSA_SIGN || + info->pk.type == WC_PK_TYPE_ECDSA_VERIFY || + info->pk.type == WC_PK_TYPE_ECDH) + { + if (myCtx->pendingCount++ < TEST_PEND_COUNT) return WC_PENDING_E; + myCtx->pendingCount = 0; + } +#endif + + #ifndef NO_RSA + if (info->pk.type == WC_PK_TYPE_RSA) { + /* set devId to invalid, so software is used */ + info->pk.rsa.key->devId = INVALID_DEVID; + + switch (info->pk.rsa.type) { + case RSA_PUBLIC_ENCRYPT: + case RSA_PUBLIC_DECRYPT: + /* perform software based RSA public op */ + ret = wc_RsaFunction( + info->pk.rsa.in, info->pk.rsa.inLen, + info->pk.rsa.out, info->pk.rsa.outLen, + info->pk.rsa.type, info->pk.rsa.key, info->pk.rsa.rng); + break; + case RSA_PRIVATE_ENCRYPT: + case RSA_PRIVATE_DECRYPT: + /* perform software based RSA private op */ + ret = wc_RsaFunction( + info->pk.rsa.in, info->pk.rsa.inLen, + info->pk.rsa.out, info->pk.rsa.outLen, + info->pk.rsa.type, info->pk.rsa.key, info->pk.rsa.rng); + break; + } + + /* reset devId */ + info->pk.rsa.key->devId = devIdArg; + } + #endif + #ifdef HAVE_ECC + if (info->pk.type == WC_PK_TYPE_EC_KEYGEN) { + /* set devId to invalid, so software is used */ + info->pk.eckg.key->devId = INVALID_DEVID; + + ret = wc_ecc_make_key_ex(info->pk.eckg.rng, info->pk.eckg.size, + info->pk.eckg.key, info->pk.eckg.curveId); + + /* reset devId */ + info->pk.eckg.key->devId = devIdArg; + } + else if (info->pk.type == WC_PK_TYPE_ECDSA_SIGN) { + /* set devId to invalid, so software is used */ + info->pk.eccsign.key->devId = INVALID_DEVID; + + ret = wc_ecc_sign_hash( + info->pk.eccsign.in, info->pk.eccsign.inlen, + info->pk.eccsign.out, info->pk.eccsign.outlen, + info->pk.eccsign.rng, info->pk.eccsign.key); + + /* reset devId */ + info->pk.eccsign.key->devId = devIdArg; + } + else if (info->pk.type == WC_PK_TYPE_ECDSA_VERIFY) { + /* set devId to invalid, so software is used */ + info->pk.eccverify.key->devId = INVALID_DEVID; + + ret = wc_ecc_verify_hash( + info->pk.eccverify.sig, info->pk.eccverify.siglen, + info->pk.eccverify.hash, info->pk.eccverify.hashlen, + info->pk.eccverify.res, info->pk.eccverify.key); + + /* reset devId */ + info->pk.eccverify.key->devId = devIdArg; + } + else if (info->pk.type == WC_PK_TYPE_ECDH) { + /* set devId to invalid, so software is used */ + info->pk.ecdh.private_key->devId = INVALID_DEVID; + + ret = wc_ecc_shared_secret( + info->pk.ecdh.private_key, info->pk.ecdh.public_key, + info->pk.ecdh.out, info->pk.ecdh.outlen); + + /* reset devId */ + info->pk.ecdh.private_key->devId = devIdArg; + } + #endif /* HAVE_ECC */ + } + + (void)devIdArg; + (void)myCtx; + + return ret; +} +#endif /* WOLF_CRYPTO_CB */ + +/* ---------------------------------------------------------------------------*/ +/* --- Example PK (Public Key) Callback --- */ +/* ---------------------------------------------------------------------------*/ +#ifdef HAVE_PK_CALLBACKS + +#endif + diff --git a/examples/async/async_tls.h b/examples/async/async_tls.h new file mode 100644 index 000000000..d5403e24f --- /dev/null +++ b/examples/async/async_tls.h @@ -0,0 +1,42 @@ +/* async-tls.h + * + * Copyright (C) 2006-2023 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +#ifndef WOLFSSL_ASYNC_TLS_EXAMPLES_H +#define WOLFSSL_ASYNC_TLS_EXAMPLES_H + +#define DEFAULT_PORT 11111 +#define TEST_BUF_SZ 256 + +#ifdef WOLF_CRYPTO_CB +/* Example custom context for crypto callback */ +typedef struct { + int pendingCount; /* track pending tries test count */ +} AsyncTlsCryptoCbCtx; +int AsyncTlsCryptoCb(int devIdArg, wc_CryptoInfo* info, void* ctx); +#endif /* WOLF_CRYPTO_CB */ + + +int client_async_test(int argc, char** argv); +int server_async_test(int argc, char** argv); + + +#endif /* WOLFSSL_ASYNC_TLS_EXAMPLES_H */ diff --git a/examples/async/include.am b/examples/async/include.am new file mode 100644 index 000000000..b8a611750 --- /dev/null +++ b/examples/async/include.am @@ -0,0 +1,24 @@ +# vim:ft=automake +# All paths should be given relative to the root + +if BUILD_ASYNCCRYPT +noinst_HEADERS += examples/async/async_tls.h + +noinst_PROGRAMS += examples/async/async_client +examples_async_async_client_SOURCES = examples/async/async_client.c examples/async/async_tls.c +examples_async_async_client_LDADD = src/libwolfssl@LIBSUFFIX@.la $(LIB_STATIC_ADD) +examples_async_async_client_DEPENDENCIES = src/libwolfssl@LIBSUFFIX@.la +examples_async_async_client_CFLAGS = $(AM_CFLAGS) + +noinst_PROGRAMS += examples/async/async_server +examples_async_async_server_SOURCES = examples/async/async_server.c examples/async/async_tls.c +examples_async_async_server_LDADD = src/libwolfssl@LIBSUFFIX@.la $(LIB_STATIC_ADD) +examples_async_async_server_DEPENDENCIES = src/libwolfssl@LIBSUFFIX@.la +examples_async_async_server_CFLAGS = $(AM_CFLAGS) +endif + +dist_example_DATA+= examples/async/async_server.c +dist_example_DATA+= examples/async/async_client.c +DISTCLEANFILES+= examples/async/.libs/async_server +DISTCLEANFILES+= examples/async/.libs/async_client +EXTRA_DIST += examples/async/README.md diff --git a/examples/include.am b/examples/include.am index 1ff74a0a3..4b7ad2f87 100644 --- a/examples/include.am +++ b/examples/include.am @@ -1,6 +1,7 @@ # vim:ft=automake # All paths should be given relative to the root +include examples/async/include.am include examples/benchmark/include.am include examples/client/include.am include examples/echoclient/include.am diff --git a/rpm/spec.in b/rpm/spec.in index 163a4e4bd..01a4b5833 100644 --- a/rpm/spec.in +++ b/rpm/spec.in @@ -67,10 +67,12 @@ mkdir -p $RPM_BUILD_ROOT/ %defattr(-,root,root,-) %doc AUTHORS ChangeLog.md COPYING README README.md %{_docdir}/wolfssl/taoCert.txt -%{_docdir}/wolfssl/example/echoserver.c +%{_docdir}/wolfssl/example/async_client.c +%{_docdir}/wolfssl/example/async_server.c +%{_docdir}/wolfssl/example/client.c %{_docdir}/wolfssl/example/server.c %{_docdir}/wolfssl/example/echoclient.c -%{_docdir}/wolfssl/example/client.c +%{_docdir}/wolfssl/example/echoserver.c %{_docdir}/wolfssl/example/sctp-client.c %{_docdir}/wolfssl/example/sctp-server.c %{_docdir}/wolfssl/example/sctp-client-dtls.c diff --git a/wolfcrypt/src/wolfevent.c b/wolfcrypt/src/wolfevent.c index bcf1d9dcf..01ddd1131 100644 --- a/wolfcrypt/src/wolfevent.c +++ b/wolfcrypt/src/wolfevent.c @@ -180,8 +180,12 @@ int wolfEventQueue_Remove(WOLF_EVENT_QUEUE* queue, WOLF_EVENT* event) else { WOLF_EVENT* next = event->next; WOLF_EVENT* prev = event->prev; - next->prev = prev; - prev->next = next; + if ((next == NULL) || (prev == NULL)) { + ret = BAD_STATE_E; + } else { + next->prev = prev; + prev->next = next; + } } queue->count--;