diff --git a/.gitignore b/.gitignore index f8366c6a..b135f1e2 100644 --- a/.gitignore +++ b/.gitignore @@ -161,3 +161,11 @@ pk/ED25519/gen_key_files pk/ED25519/sign_and_verify wolfCLU/tests/somejunk/*somejunk*.txt + +embedded/tls-client-server +embedded/tls-sock-client +embedded/tls-sock-client-ca +embedded/tls-sock-server +embedded/tls-sock-server-ca +embedded/tls-sock-threaded +embedded/tls-threaded diff --git a/embedded/Makefile b/embedded/Makefile new file mode 100644 index 00000000..f2c494bb --- /dev/null +++ b/embedded/Makefile @@ -0,0 +1,102 @@ +# TLS Examples Makefile +CC = gcc +LIB_PATH = /usr/local +CFLAGS = -Wall -I$(LIB_PATH)/include +LIBS = -L$(LIB_PATH)/lib -lm + +# option variables +DYN_LIB = -lwolfssl +STATIC_LIB = $(LIB_PATH)/lib/libwolfssl.a +DEBUG_FLAGS = -g -DDEBUG +DEBUG_INC_PATHS = -MD +OPTIMIZE = -Os + +# Options +#CFLAGS+=$(DEBUG_FLAGS) +CFLAGS+=$(OPTIMIZE) +#CFLAGS+=$(QAT_FLAGS) +#LIBS+=$(QAT_LIBS) +#LIBS+=$(STATIC_LIB) +LIBS+=$(DYN_LIB) + +# build targets +SRC=$(wildcard *.c) +TARGETS=$(patsubst %.c, %, $(SRC)) +LINUX_SPECIFIC=client-tls-perf \ + server-tls-epoll-perf \ + server-tls-epoll-threaded + + +# Intel QuickAssist +QAT_PATH=../../QAT1.6 +QAT_FLAGS=-DDO_CRYPTO -DUSER_SPACE \ + -I$(QAT_PATH)/quickassist/include \ + -I$(QAT_PATH)/quickassist/include/lac \ + -I$(QAT_PATH)/quickassist/utilities/osal/include \ + -I$(QAT_PATH)/quickassist/utilities/osal/src/linux/user_space/include \ + -I$(QAT_PATH)/quickassist/lookaside/access_layer/include \ + -I$(QAT_PATH)/quickassist/lookaside/access_layer/src/common/include +QAT_LIBS=-L$(QAT_PATH) -ladf_proxy -losal -licp_qa_al_s -lpthread + + +# OS / CPU Detection +OS_DET=UNKNOWN +CPU_DET=UNKNOWN +ifeq ($(OS),Windows_NT) + OS_DET=WIN32 + ifeq ($(PROCESSOR_ARCHITEW6432),AMD64) + CPU_DET=AMD64 + else + ifeq ($(PROCESSOR_ARCHITECTURE),AMD64) + CPU_DET=AMD64 + endif + ifeq ($(PROCESSOR_ARCHITECTURE),x86) + CPU_DET=IA32 + endif + endif +else + UNAME_S := $(shell uname -s) + ifeq ($(UNAME_S),Linux) + OS_DET=LINUX + endif + ifeq ($(UNAME_S),Darwin) + OS_DET=OSX + endif + UNAME_P := $(shell uname -p) + ifeq ($(UNAME_P),x86_64) + CPU_DET=AMD64 + endif + ifneq ($(filter %86,$(UNAME_P)),) + CPU_DET=IA32 + endif + ifneq ($(filter arm%,$(UNAME_P)),) + CPU_DET=ARM + endif +endif + +# $(info $$OS_DET is [${OS_DET}]) +# $(info $$CPU_DET is [${CPU_DET}]) + +.PHONY: clean all + +ifneq ($(OS_DET),LINUX) +all: $(filter-out $(LINUX_SPECIFIC), $(TARGETS)) +else +all: $(TARGETS) +endif + +debug: CFLAGS+=$(DEBUG_FLAGS) +debug: all + +# add the -pthread flag to any threaded examples +%-threaded: CFLAGS+=-pthread + +# compile tcp examples without the LIBS variable +%-tcp: LIBS= + +# build template +%: %.c *.h + $(CC) -o $@ $< $(CFLAGS) $(LIBS) + +clean: + rm -f $(TARGETS) diff --git a/embedded/README.md b/embedded/README.md new file mode 100644 index 00000000..5244983e --- /dev/null +++ b/embedded/README.md @@ -0,0 +1,290 @@ +# Examples for Embedded systems + +## Building + +### Build and install wolfSSL + +``` +./configure && make && sudo make install +``` + +### Build Example + +``` +make +gcc -o tls-sock-client tls-sock-client.c -Wall -I/usr/local/include -Os -L/usr/local/lib -lm -lwolfssl +gcc -o tls-sock-server-ca tls-sock-server-ca.c -Wall -I/usr/local/include -Os -L/usr/local/lib -lm -lwolfssl +gcc -o tls-sock-threaded tls-sock-threaded.c -Wall -I/usr/local/include -Os -pthread -L/usr/local/lib -lm -lwolfssl +gcc -o tls-client-server tls-client-server.c -Wall -I/usr/local/include -Os -L/usr/local/lib -lm -lwolfssl +gcc -o tls-sock-server tls-sock-server.c -Wall -I/usr/local/include -Os -L/usr/local/lib -lm -lwolfssl +gcc -o tls-sock-client-ca tls-sock-client-ca.c -Wall -I/usr/local/include -Os -L/usr/local/lib -lm -lwolfssl +gcc -o tls-threaded tls-threaded.c -Wall -I/usr/local/include -Os -pthread -L/usr/local/lib -lm -lwolfssl +``` + +### Debug + +To enable debug change the Makefile to: + +``` +CFLAGS+=$(DEBUG_FLAGS) +#CFLAGS+=$(OPTIMIZE) +``` + +Build wolfSSL adding `--enable-debug` to the ./configure. + +To enable using the static library change the Makefile to: + +``` +LIBS+=$(STATIC_LIB) +#LIBS+=$(DYN_LIB) +``` + +Build wolfSSL adding `--disable-shared` to the ./configure. + + +## Usage + +### `tls-client-server` + +This example demonstrates a client and server communicating through buffers (i.e. not sockets.) wolfSSL_SetIOSend() and wolfSSL_SetIORecv() are used to set the callback functions to send and receive TLS message data. Note that wolfSSL will request as many bytes as needed to process a TLS message and expects a return of WOLFSSL_CBIO_ERR_WANT_READ when no data is available. Similarly, the return code from the send function must be the number of bytes successfully dealt with or WOLFSSL_CBIO_ERR_WANT_WRITE when no bytes could be sent. + +``` +./tls-client-server +Client waiting for server +Server waiting for server +Client waiting for server +Handshake complete + +Client Sending: +GET /index.html HTTP/1.0 + + +Server Received: +GET /index.html HTTP/1.0 + + +Server Sending: +HTTP/1.1 200 OK +Content-Type: text/html +Connection: close + + +
+wolfSSL has successfully performed handshake!
+ + + +Client Received: +HTTP/1.1 200 OK +Content-Type: text/html +Connection: close + + + +wolfSSL has successfully performed handshake!
+ + +Done +``` + +### `tls-threaded` + +This example demonstrates a client and server, in separate threads, communicating through buffers (i.e. not sockets.) wolfSSL_SetIOSend() and wolfSSL_SetIORecv() are used to set the callback functions to send and receive TLS message data. Note that wolfSSL will request as many bytes as needed to process a TLS message and expects a return of WOLFSSL_CBIO_ERR_WANT_READ when no data is available. Similarly, the return code from the send function must be the number of bytes successfully dealt with or WOLFSSL_CBIO_ERR_WANT_WRITE when no bytes could be sent. + +``` +./tls-threaded +Handshake complete +Sending: +GET /index.html HTTP/1.0 + + +Received: +GET /index.html HTTP/1.0 + + +Sending: +HTTP/1.1 200 OK +Content-Type: text/html +Connection: close + + + +wolfSSL has successfully performed handshake!
+ + + +Server Return: 0 +Received: +HTTP/1.1 200 OK +Content-Type: text/html +Connection: close + + + +wolfSSL has successfully performed handshake!
+ + + +Client Return: 0 +Done +``` + +### `tls-sock-client` + +This example demonstrates a TLS client using sockets. The client attempts to connect to: localhost:11111. The client will downgrade to the highest version supported by both peers (wolfSSLv23_client_method().) + + +``` +[./tls-sock-server] +./tls-sock-client +SSL version is TLSv1.2 +SSL cipher suite is TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 +SSL curve name is SECP256R1 +Sending: +GET /index.html HTTP/1.0 + + +Receive: +HTTP/1.1 200 OK +Content-Type: text/html +Connection: close + + + +wolfSSL has successfully performed handshake!
+ + +Peer closed socket +Done +``` + +### `tls-sock-client-ca` + +This example demonstrates a TLS client performing client authentication and using sockets. The client attempts to connect to: localhost:11111. The client will downgrade to the highest version supported by both peers (wolfSSLv23_client_method().) + +``` +[./tls-sock-server-ca] +./tls-sock-client-ca +SSL version is TLSv1.2 +SSL cipher suite is TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 +SSL curve name is SECP256R1 +Sending: +GET /index.html HTTP/1.0 + + +Receive: +HTTP/1.1 200 OK +Content-Type: text/html +Connection: close + + + +wolfSSL has successfully performed handshake!
+ + +Peer closed socket +Done +``` + +### `tls-sock-server` + +This example demonstrates a TLS server using sockets. The server accepts connections on: localhost:11111. The server will downgrade to the highest version supported by both peers (wolfSSLv23_server_method().) + +``` +./tls-sock-server +[./tls-sock-client] +SSL version is TLSv1.2 +SSL cipher suite is TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 +SSL curve name is SECP256R1 +Receive: +GET /index.html HTTP/1.0 + +Sending: +HTTP/1.1 200 OK +Content-Type: text/html +Connection: close + + + +wolfSSL has successfully performed handshake!
+ + + +[./tls-sock-client] +SSL version is TLSv1.2 +SSL cipher suite is TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 +SSL curve name is SECP256R1 +Receive: +GET /index.html HTTP/1.0 + +Sending: +HTTP/1.1 200 OK +Content-Type: text/html +Connection: close + + + +wolfSSL has successfully performed handshake!
+ + + +^C +``` + +### `tls-sock-server-ca` + +This example demonstrates a TLS server performing client authentication using sockets. The server accepts connections on: localhost:11111. The server will downgrade to the highest version supported by both peers (wolfSSLv23_server_method().) + +``` +./tls-sock-server-ca +[./tls-sock-client-ca] +SSL version is TLSv1.2 +SSL cipher suite is TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 +SSL curve name is SECP256R1 +Receive: +GET /index.html HTTP/1.0 + +Sending: +HTTP/1.1 200 OK +Content-Type: text/html +Connection: close + + + +wolfSSL has successfully performed handshake!
+ + + +^C +``` + +## Support + +For questions please email us at support@wolfssl.com. diff --git a/embedded/certs.h b/embedded/certs.h new file mode 100644 index 00000000..18ed0761 --- /dev/null +++ b/embedded/certs.h @@ -0,0 +1,62 @@ +/* certs.h + * + * Copyright (C) 2006-2019 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 + */ + + +/* Use the certificate buffers instead of using filesystem. */ +#ifndef NO_RSA + #define USE_CERT_BUFFERS_2048 + #define SERVER_CERT server_cert_der_2048 + #define SERVER_CERT_LEN sizeof_server_cert_der_2048 + #define SERVER_KEY server_key_der_2048 + #define SERVER_KEY_LEN sizeof_server_key_der_2048 + #define CA_CERTS ca_cert_der_2048 + #define CA_CERTS_LEN sizeof_ca_cert_der_2048 + #define CLIENT_CERT client_cert_der_2048 + #define CLIENT_CERT_LEN sizeof_client_cert_der_2048 + #define CLIENT_KEY client_key_der_2048 + #define CLIENT_KEY_LEN sizeof_client_key_der_2048 +#elif defined(HAVE_ECC) + #define USE_CERT_BUFFERS_256 + #define SERVER_CERT serv_ecc_der_256 + #define SERVER_CERT_LEN sizeof_serv_ecc_der_256 + #define SERVER_KEY ecc_key_der_256 + #define SERVER_KEY_LEN sizeof_ecc_key_der_256 + #define CA_CERTS ca_ecc_cert_der_256 + #define CA_CERTS_LEN sizeof_ca_ecc_cert_der_256 + #define CLIENT_CERT cliecc_cert_der_256 + #define CLIENT_CERT_LEN sizeof_cliecc_cert_der_256 + #define CLIENT_KEY ecc_clikey_der_256 + #define CLIENT_KEY_LEN sizeof_ecc_clikey_der_256 +#elif defined(HAVE_ED25519) + #define SERVER_CERT server_ed25519_cert + #define SERVER_CERT_LEN sizeof_server_ed25519_cert + #define SERVER_KEY server_ed25519_key + #define SERVER_KEY_LEN sizeof_server_ed25519_key + #define CA_CERTS ca_ed25519_cert + #define CA_CERTS_LEN sizeof_ca_ed25519_cert + #define CLIENT_CERT client_ed25519_cert + #define CLIENT_CERT_LEN sizeof_client_ed25519_cert + #define CLIENT_KEY client_ed25519_key + #define CLIENT_KEY_LEN sizeof_client_ed25519_key +#endif + +#includewolfSSL has successfully performed handshake!
\n" + "\n" + "\n"; + + +/* Client attempts to read data from server. */ +static int recv_client(WOLFSSL* ssl, char* buff, int sz, void* ctx) +{ + if (client_buffer_sz > 0) { + if (sz > client_buffer_sz) + sz = client_buffer_sz; + XMEMCPY(buff, client_buffer, sz); + if (sz < client_buffer_sz) { + XMEMMOVE(client_buffer, client_buffer + sz, client_buffer_sz - sz); + } + client_buffer_sz -= sz; + } + else + sz = WOLFSSL_CBIO_ERR_WANT_READ; + + return sz; +} + +/* Client attempts to write data to server. */ +static int send_client(WOLFSSL* ssl, char* buff, int sz, void* ctx) +{ + if (server_buffer_sz < BUFFER_SIZE) + { + if (sz > BUFFER_SIZE - server_buffer_sz) + sz = BUFFER_SIZE - server_buffer_sz; + XMEMCPY(server_buffer + server_buffer_sz, buff, sz); + server_buffer_sz += sz; + } + else + sz = WOLFSSL_CBIO_ERR_WANT_WRITE; + + return sz; +} + +/* Server attempts to read data from client. */ +static int recv_server(WOLFSSL* ssl, char* buff, int sz, void* ctx) +{ + + if (server_buffer_sz > 0) { + if (sz > server_buffer_sz) + sz = server_buffer_sz; + XMEMCPY(buff, server_buffer, sz); + if (sz < server_buffer_sz) { + XMEMMOVE(server_buffer, server_buffer + sz, server_buffer_sz - sz); + } + server_buffer_sz -= sz; + } + else + sz = WOLFSSL_CBIO_ERR_WANT_READ; + + return sz; +} + +/* Server attempts to write data to client. */ +static int send_server(WOLFSSL* ssl, char* buff, int sz, void* ctx) +{ + if (client_buffer_sz < BUFFER_SIZE) + { + if (sz > BUFFER_SIZE - client_buffer_sz) + sz = BUFFER_SIZE - client_buffer_sz; + XMEMCPY(client_buffer + client_buffer_sz, buff, sz); + client_buffer_sz += sz; + } + else + sz = WOLFSSL_CBIO_ERR_WANT_WRITE; + + return sz; +} + + +/* Create a new wolfSSL client with a server CA certificate. */ +static int wolfssl_client_new(WOLFSSL_CTX** ctx, WOLFSSL** ssl) +{ + int ret = 0; + WOLFSSL_CTX* client_ctx = NULL; + WOLFSSL* client_ssl = NULL; + + /* Create and initialize WOLFSSL_CTX */ + if ((client_ctx = wolfSSL_CTX_new_ex(wolfTLSv1_2_client_method(), + HEAP_HINT_CLIENT)) == NULL) { + printf("ERROR: failed to create WOLFSSL_CTX\n"); + ret = -1; + } + + if (ret == 0) { + /* Load CA certificates into WOLFSSL_CTX */ + if (wolfSSL_CTX_load_verify_buffer(client_ctx, CA_CERTS, CA_CERTS_LEN, + WOLFSSL_FILETYPE_ASN1) != WOLFSSL_SUCCESS) { + printf("ERROR: failed to load CA certificate\n"); + ret = -1; + } + } + + if (ret == 0) { + /* Register callbacks */ + wolfSSL_SetIORecv(client_ctx, recv_client); + wolfSSL_SetIOSend(client_ctx, send_client); + } + + if (ret == 0) { + /* Create a WOLFSSL object */ + if ((client_ssl = wolfSSL_new(client_ctx)) == NULL) { + printf("ERROR: failed to create WOLFSSL object\n"); + ret = -1; + } + } + + if (ret == 0) { + /* make wolfSSL object nonblocking */ + wolfSSL_set_using_nonblock(client_ssl, 1); + } + + if (ret == 0) { + *ctx = client_ctx; + *ssl = client_ssl; + } + else { + if (client_ssl != NULL) + wolfSSL_free(client_ssl); + if (client_ctx != NULL) + wolfSSL_CTX_free(client_ctx); + } + + return ret; +} + +/* Client connecting to server using TLS */ +static int wolfssl_client_connect(WOLFSSL* client_ssl) +{ + int ret = 0; + + if (wolfSSL_connect(client_ssl) != WOLFSSL_SUCCESS) { + if (wolfSSL_want_read(client_ssl)) { + printf("Client waiting for server\n"); + } + else if (wolfSSL_want_write(client_ssl)) { + printf("Client waiting for buffer\n"); + } + else + ret = -1; + } + + return ret; +} + + +/* Create a new wolfSSL server with a certificate for authentication. */ +static int wolfssl_server_new(WOLFSSL_CTX** ctx, WOLFSSL** ssl) +{ + int ret = 0; + WOLFSSL_CTX* server_ctx = NULL; + WOLFSSL* server_ssl = NULL; + + /* Create and initialize WOLFSSL_CTX */ + if ((server_ctx = wolfSSL_CTX_new_ex(wolfTLSv1_2_server_method(), + HEAP_HINT_SERVER)) == NULL) { + printf("ERROR: failed to create WOLFSSL_CTX\n"); + ret = -1; + } + + if (ret == 0) { + /* Load client certificates into WOLFSSL_CTX */ + if (wolfSSL_CTX_use_certificate_buffer(server_ctx, SERVER_CERT, + SERVER_CERT_LEN, WOLFSSL_FILETYPE_ASN1) != WOLFSSL_SUCCESS) { + printf("ERROR: failed to load server certificate\n"); + ret = -1; + } + } + + if (ret == 0) { + /* Load client certificates into WOLFSSL_CTX */ + if (wolfSSL_CTX_use_PrivateKey_buffer(server_ctx, + SERVER_KEY, SERVER_KEY_LEN, WOLFSSL_FILETYPE_ASN1) != + WOLFSSL_SUCCESS) { + printf("ERROR: failed to load server key\n"); + ret = -1; + } + } + + if (ret == 0) { + /* Register callbacks */ + wolfSSL_SetIORecv(server_ctx, recv_server); + wolfSSL_SetIOSend(server_ctx, send_server); + } + + if (ret == 0) { + /* Create a WOLFSSL object */ + if ((server_ssl = wolfSSL_new(server_ctx)) == NULL) { + printf("ERROR: failed to create WOLFSSL object\n"); + ret = -1; + } + } + + if (ret == 0) { + /* make wolfSSL object nonblocking */ + wolfSSL_set_using_nonblock(server_ssl, 1); + } + + if (ret == 0) { + *ctx = server_ctx; + *ssl = server_ssl; + } + else { + if (server_ssl != NULL) + wolfSSL_free(server_ssl); + if (server_ctx != NULL) + wolfSSL_CTX_free(server_ctx); + } + return ret; +} + +/* Server accepting a client using TLS */ +static int wolfssl_server_accept(WOLFSSL* server_ssl) +{ + int ret = 0; + + if (wolfSSL_accept(server_ssl) != WOLFSSL_SUCCESS) { + if (wolfSSL_want_read(server_ssl)) { + printf("Server waiting for server\n"); + } + else if (wolfSSL_want_write(server_ssl)) { + printf("Server waiting for buffer\n"); + } + else + ret = -1; + } + + return ret; +} + + +/* Send application data. */ +static int wolfssl_send(WOLFSSL* ssl, const char* msg) +{ + int ret; + + printf("%s", msg); + ret = wolfSSL_write(ssl, msg, XSTRLEN(msg)); + if (ret < XSTRLEN(msg)) + ret = -1; + else + ret = 0; + + return ret; +} + +/* Receive application data. */ +static int wolfssl_recv(WOLFSSL* ssl) +{ + int ret; + byte reply[256]; + + ret = wolfSSL_read(ssl, reply, sizeof(reply)-1); + if (ret > 0) { + reply[ret] = '\0'; + printf("%s", reply); + ret = 0; + } + + return ret; +} + + +/* Free the WOLFSSL object and context. */ +static void wolfssl_free(WOLFSSL_CTX* ctx, WOLFSSL* ssl) +{ + if (ssl != NULL) + wolfSSL_free(ssl); + if (ctx != NULL) + wolfSSL_CTX_free(ctx); +} + + +/* Display dynamic memory usage statistics. */ +static void wolfssl_memstats(WOLFSSL* ssl) +{ +#ifdef WOLFSSL_STATIC_MEMORY + WOLFSSL_MEM_CONN_STATS ssl_stats; + + XMEMSET(&ssl_stats, 0 , sizeof(ssl_stats)); + + if (wolfSSL_is_static_memory(ssl, &ssl_stats) != 1) + printf("static memory was not used with ssl"); + else { + printf("*** This is memory state before wolfSSL_free is called\n"); + printf("peak connection memory = %d\n", ssl_stats.peakMem); + printf("current memory in use = %d\n", ssl_stats.curMem); + printf("peak connection allocs = %d\n", ssl_stats.peakAlloc); + printf("current connection allocs = %d\n",ssl_stats.curAlloc); + printf("total connection allocs = %d\n",ssl_stats.totalAlloc); + printf("total connection frees = %d\n\n", ssl_stats.totalFr); + } +#endif +} + +/* Display dynamic memory usage statistics of the client connection. */ +static void wolfssl_client_memstats(WOLFSSL* client_ssl) +{ +#ifdef WOLFSSL_STATIC_MEMORY + printf("Client Memory Stats\n"); +#endif + wolfssl_memstats(client_ssl); +} + +/* Display dynamic memory usage statistics of the server connection. */ +static void wolfssl_server_memstats(WOLFSSL* server_ssl) +{ +#ifdef WOLFSSL_STATIC_MEMORY + printf("Server Memory Stats\n"); +#endif + wolfssl_memstats(server_ssl); +} + +/* Main entry point. */ +int main(int argc, char* argv[]) +{ + int ret = 0; + WOLFSSL_CTX* client_ctx = NULL; + WOLFSSL* client_ssl = NULL; + WOLFSSL_CTX* server_ctx = NULL; + WOLFSSL* server_ssl = NULL; + +#if defined(DEBUG_WOLFSSL) + wolfSSL_Debugging_ON(); +#endif + /* Initialize wolfSSL library. */ + wolfSSL_Init(); + +#ifdef WOLFSSL_STATIC_MEMORY + if (wc_LoadStaticMemory(&HEAP_HINT_SERVER, gTestMemoryServer, + sizeof(gTestMemoryServer), + WOLFMEM_GENERAL | WOLFMEM_TRACK_STATS, 1) != 0) { + printf("unable to load static memory"); + ret = -1; + } + if (wc_LoadStaticMemory(&HEAP_HINT_CLIENT, gTestMemoryClient, + sizeof(gTestMemoryClient), + WOLFMEM_GENERAL | WOLFMEM_TRACK_STATS, 1) != 0) { + printf("unable to load static memory"); + ret = -1; + } +#endif + + /* Create server and client SSL objects. */ + if (ret == 0) + ret = wolfssl_server_new(&server_ctx, &server_ssl); + if (ret == 0) + ret = wolfssl_client_new(&client_ctx, &client_ssl); + + /* Loop to perform SSL handshake. */ + while (ret == 0) { + ret = wolfssl_client_connect(client_ssl); + if (ret == 0) + ret = wolfssl_server_accept(server_ssl); + if (ret == 0 && wolfSSL_is_init_finished(client_ssl) && + wolfSSL_is_init_finished(server_ssl)) { + break; + } + } + + if (ret == 0) + printf("Handshake complete\n"); + + /* Send and receive HTTP messages. */ + if (ret == 0) { + printf("\nClient Sending:\n"); + ret = wolfssl_send(client_ssl, msgHTTPGet); + } + if (ret == 0) { + printf("\nServer Received:\n"); + ret = wolfssl_recv(server_ssl); + } + if (ret == 0) { + printf("\nServer Sending:\n"); + ret = wolfssl_send(server_ssl, msgHTTPIndex); + } + if (ret == 0) { + printf("\nClient Received:\n"); + ret = wolfssl_recv(client_ssl); + } + + /* Display memory statistics. */ + wolfssl_client_memstats(client_ssl); + wolfssl_server_memstats(server_ssl); + + /* Dispose of SSL objects. */ + wolfssl_free(client_ctx, client_ssl); + wolfssl_free(server_ctx, server_ssl); + + /* Cleanup wolfSSL library. */ + wolfSSL_Cleanup(); + + if (ret == 0) + printf("Done\n"); + else { + char buffer[80]; + printf("Error: %d, %s\n", ret, wolfSSL_ERR_error_string(ret, buffer)); + } + + return (ret == 0) ? 0 : 1; +} + diff --git a/embedded/tls-info.h b/embedded/tls-info.h new file mode 100644 index 00000000..b57cb8fa --- /dev/null +++ b/embedded/tls-info.h @@ -0,0 +1,232 @@ +/* tls-info.h + * + * Copyright (C) 2006-2019 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 + */ + +static const char* client_showpeer_msg[][8] = { + /* English */ + { + "SSL version is", + "SSL cipher suite is", + "SSL curve name is", + "SSL DH size is", + "SSL reused session", + "Alternate cert chain used", + "peer's cert info:", + NULL + }, +#ifndef NO_MULTIBYTE_PRINT + /* Japanese */ + { + "SSL バージョンは", + "SSL 暗号スイートは", + "SSL 曲線名は", + "SSL DH サイズは", + "SSL 再利用セッション", + "代替証明チェーンを使用", + "相手方証明書情報", + NULL + }, +#endif +}; + +#if defined(KEEP_PEER_CERT) || defined(SESSION_CERTS) +static const char* client_showx509_msg[][5] = { + /* English */ + { + "issuer", + "subject", + "altname", + "serial number", + NULL + }, +#ifndef NO_MULTIBYTE_PRINT + /* Japanese */ + { + "発行者", + "サブジェクト", + "代替名", + "シリアル番号", + NULL + }, +#endif +}; + + +/* lng_index is to specify the language for displaying message. */ +/* 0:English, 1:Japanese */ +static WC_INLINE void ShowX509Ex(WOLFSSL_X509* x509, const char* hdr, + int lng_index) +{ + char* altName; + char* issuer; + char* subject; + byte serial[32]; + int ret; + int sz = sizeof(serial); + const char** words = client_showx509_msg[lng_index]; + + if (x509 == NULL) { + printf("%s No Cert\n", hdr); + return; + } + + issuer = wolfSSL_X509_NAME_oneline( + wolfSSL_X509_get_issuer_name(x509), 0, 0); + subject = wolfSSL_X509_NAME_oneline( + wolfSSL_X509_get_subject_name(x509), 0, 0); + + printf("%s\n %s : %s\n %s: %s\n", hdr, words[0], issuer, words[1], subject); + + while ( (altName = wolfSSL_X509_get_next_altname(x509)) != NULL) + printf(" %s = %s\n", words[2], altName); + + ret = wolfSSL_X509_get_serial_number(x509, serial, &sz); + if (ret == WOLFSSL_SUCCESS) { + int i; + int strLen; + char serialMsg[80]; + + /* testsuite has multiple threads writing to stdout, get output + message ready to write once */ + strLen = sprintf(serialMsg, " %s", words[3]); + for (i = 0; i < sz; i++) + sprintf(serialMsg + strLen + (i*3), ":%02x ", serial[i]); + printf("%s\n", serialMsg); + } + + XFREE(subject, 0, DYNAMIC_TYPE_OPENSSL); + XFREE(issuer, 0, DYNAMIC_TYPE_OPENSSL); + +#if defined(OPENSSL_EXTRA) && defined(SHOW_CERTS) + { + WOLFSSL_BIO* bio; + char buf[256]; /* should be size of ASN_NAME_MAX */ + int textSz; + + + /* print out domain component if certificate has it */ + textSz = wolfSSL_X509_NAME_get_text_by_NID( + wolfSSL_X509_get_subject_name(x509), NID_domainComponent, + buf, sizeof(buf)); + if (textSz > 0) { + printf("Domain Component = %s\n", buf); + } + + bio = wolfSSL_BIO_new(wolfSSL_BIO_s_file()); + if (bio != NULL) { + wolfSSL_BIO_set_fp(bio, stdout, BIO_NOCLOSE); + wolfSSL_X509_print(bio, x509); + wolfSSL_BIO_free(bio); + } + } +#endif +} +#endif + +#if defined(SESSION_CERTS) && defined(SHOW_CERTS) +static WC_INLINE void ShowX509Chain(WOLFSSL_X509_CHAIN* chain, int count, + const char* hdr) +{ + int i; + int length; + unsigned char buffer[3072]; + WOLFSSL_X509* chainX509; + + for (i = 0; i < count; i++) { + wolfSSL_get_chain_cert_pem(chain, i, buffer, sizeof(buffer), &length); + buffer[length] = 0; + printf("\n%s: %d has length %d data = \n%s\n", hdr, i, length, buffer); + + chainX509 = wolfSSL_get_chain_X509(chain, i); + if (chainX509) + ShowX509(chainX509, hdr); + else + printf("get_chain_X509 failed\n"); + wolfSSL_FreeX509(chainX509); + } +} +#endif + +static WC_INLINE void showPeerEx(WOLFSSL* ssl, int lng_index) +{ + WOLFSSL_CIPHER* cipher; + const char** words = client_showpeer_msg[lng_index]; + +#ifdef HAVE_ECC + const char *name; +#endif +#ifndef NO_DH + int bits; +#endif +#ifdef KEEP_PEER_CERT + WOLFSSL_X509* peer = wolfSSL_get_peer_certificate(ssl); + if (peer) + ShowX509Ex(peer, words[6], lng_index); + else + printf("peer has no cert!\n"); + wolfSSL_FreeX509(peer); +#endif +#if defined(SHOW_CERTS) && defined(OPENSSL_EXTRA) && defined(KEEP_OUR_CERT) + ShowX509(wolfSSL_get_certificate(ssl), "our cert info:"); + printf("Peer verify result = %lu\n", wolfSSL_get_verify_result(ssl)); +#endif /* SHOW_CERTS */ + printf("%s %s\n", words[0], wolfSSL_get_version(ssl)); + + cipher = wolfSSL_get_current_cipher(ssl); +#ifdef HAVE_QSH + printf("%s %s%s\n", words[1], (wolfSSL_isQSH(ssl))? "QSH:": "", + wolfSSL_CIPHER_get_name(cipher)); +#else + printf("%s %s\n", words[1], wolfSSL_CIPHER_get_name(cipher)); +#endif +#ifdef HAVE_ECC + if ((name = wolfSSL_get_curve_name(ssl)) != NULL) + printf("%s %s\n", words[2], name); +#endif +#ifndef NO_DH + if ((bits = wolfSSL_GetDhKey_Sz(ssl)) > 0) + printf("%s %d bits\n", words[3], bits); +#endif + if (wolfSSL_session_reused(ssl)) + printf("%s\n", words[4]); +#ifdef WOLFSSL_ALT_CERT_CHAINS + if (wolfSSL_is_peer_alt_cert_chain(ssl)) + printf("%s\n", words[5]); +#endif + +#if defined(SESSION_CERTS) && defined(SHOW_CERTS) + { + WOLFSSL_X509_CHAIN* chain; + + chain = wolfSSL_get_peer_chain(ssl); + ShowX509Chain(chain, wolfSSL_get_chain_count(chain), "session cert"); + + #ifdef WOLFSSL_ALT_CERT_CHAINS + if (wolfSSL_is_peer_alt_cert_chain(ssl)) { + chain = wolfSSL_get_peer_alt_chain(ssl); + ShowX509Chain(chain, wolfSSL_get_chain_count(chain), "alt cert"); + } + #endif + } +#endif /* SESSION_CERTS && SHOW_CERTS */ + (void)ssl; +} + + diff --git a/embedded/tls-sock-client-ca.c b/embedded/tls-sock-client-ca.c new file mode 100644 index 00000000..1af1f212 --- /dev/null +++ b/embedded/tls-sock-client-ca.c @@ -0,0 +1,266 @@ +/* tls-sock-client-ca.c + * + * Copyright (C) 2006-2019 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 + */ + +#includewolfSSL has successfully performed handshake!
\n" + "\n" + "\n"; + + +/* Create a new wolfSSL CTX server with a certificate for authentication and a + * client certificate for client authentication. + */ +static int wolfssl_server_ctx_new(WOLFSSL_CTX** ctx) +{ + int ret = 0; + WOLFSSL_CTX* server_ctx = NULL; + + /* Create and initialize WOLFSSL_CTX */ + if ((server_ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())) == NULL) { + printf("ERROR: failed to create WOLFSSL_CTX\n"); + ret = -1; + } + + if (ret == 0) { + /* Load client certificates into WOLFSSL_CTX */ + if (wolfSSL_CTX_use_certificate_buffer(server_ctx, SERVER_CERT, + SERVER_CERT_LEN, WOLFSSL_FILETYPE_ASN1) != WOLFSSL_SUCCESS) { + printf("ERROR: failed to load server certificate\n"); + ret = -1; + } + } + + if (ret == 0) { + /* Load client certificates into WOLFSSL_CTX */ + if (wolfSSL_CTX_use_PrivateKey_buffer(server_ctx, SERVER_KEY, + SERVER_KEY_LEN, WOLFSSL_FILETYPE_ASN1) != WOLFSSL_SUCCESS) { + printf("ERROR: failed to load server key\n"); + ret = -1; + } + } + + if (ret == 0) { + wolfSSL_CTX_set_verify(server_ctx, WOLFSSL_VERIFY_PEER | + WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT, 0); + + /* Load server certificates into WOLFSSL_CTX */ + if (wolfSSL_CTX_load_verify_buffer(server_ctx, CLIENT_CERT, + CLIENT_CERT_LEN, WOLFSSL_FILETYPE_ASN1) != WOLFSSL_SUCCESS) { + printf("ERROR: failed to load CA certificate\n"); + ret = -1; + } + } + + if (ret == 0) { + /* Return newly created wolfSSL context */ + *ctx = server_ctx; + } + else { + if (server_ctx != NULL) + wolfSSL_CTX_free(server_ctx); + } + return ret; +} + +/* Create a new wolfSSL server with a certificate for authentication. */ +static int wolfssl_server_ssl_new(WOLFSSL_CTX* ctx, WOLFSSL** ssl) +{ + int ret = 0; + WOLFSSL* server_ssl = NULL; + + if (ret == 0) { + /* Create a WOLFSSL object */ + if ((server_ssl = wolfSSL_new(ctx)) == NULL) { + printf("ERROR: failed to create WOLFSSL object\n"); + ret = -1; + } + } + + if (ret == 0) { + /* make wolfSSL object nonblocking */ + wolfSSL_set_using_nonblock(server_ssl, 1); + } + + if (ret == 0) { + /* Return newly created wolfSSL context and object */ + *ssl = server_ssl; + } + else { + if (server_ssl != NULL) + wolfSSL_free(server_ssl); + } + + return ret; +} + +/* Server accepting a client using TLS */ +static int wolfssl_server_accept(WOLFSSL* ssl) +{ + int ret = 0; + + if (wolfSSL_accept(ssl) != WOLFSSL_SUCCESS) { + ret = wolfSSL_get_error(ssl, 0); + if (ret == WOLFSSL_ERROR_WANT_READ) + ret = 0; + else if (ret > 0) + ret = -1; + } + + return ret; +} + + +/* Send application data. */ +static int wolfssl_send(WOLFSSL* ssl, const char* msg) +{ + int ret = 0; + int len; + + printf("Sending:\n%s\n", msg); + len = wolfSSL_write(ssl, msg, XSTRLEN(msg)); + if (len < 0) + ret = len; + else if (len != XSTRLEN(msg)) + ret = -1; + + return ret; +} + +/* Receive application data. */ +static int wolfssl_recv(WOLFSSL* ssl) +{ + int ret; + int err = 0; + byte reply[80]; + int total = 0; + + printf("Receive:\n"); + do { + ret = wolfSSL_read(ssl, reply, sizeof(reply)-1); + if (ret > 0) { + reply[ret] = '\0'; + printf("%s", reply); + total += ret; + err = 0; + } + else if (ret == -1) + err = wolfSSL_get_error(ssl, 0); + } + while (err == 0 || (total == 0 && err == WOLFSSL_ERROR_WANT_READ)); + + if (total > 0 && err == WOLFSSL_ERROR_WANT_READ) + ret = 0; + + return ret; +} + +/* Establish a socket to listen on. */ +static int wolfssl_server_listen_tcp(SOCKET_T* fd) +{ + word16 port = wolfSSLPort; + + return tcp_listen(fd, &port, 1, 0, 0); +} + +/* Accept the TCP connection from the client. */ +static int wolfssl_server_accept_tcp(WOLFSSL* ssl, SOCKET_T fd, + SOCKET_T* acceptfd) +{ + int ret = 0; + SOCKET_T clientfd = WOLFSSL_SOCKET_INVALID; + + ret = tcp_accept(&fd, &clientfd); + if (ret == 0) { + *acceptfd = clientfd; + ret = tcp_set_nonblocking(&clientfd); + } + + if (ret == 0) { + if (wolfSSL_set_fd(ssl, clientfd) != WOLFSSL_SUCCESS) + ret = -1; + } + + return ret; +} + + +/* Server operations. */ +static int server(WOLFSSL_CTX* server_ctx, SOCKET_T sockfd) +{ + int ret; + WOLFSSL* server_ssl = NULL; + SOCKET_T clientfd = WOLFSSL_SOCKET_INVALID; + + do { + ret = wolfssl_server_ssl_new(server_ctx, &server_ssl); + if (ret == 0) + ret = wolfssl_server_accept_tcp(server_ssl, sockfd, &clientfd); + + while (ret == 0) { + ret = wolfssl_server_accept(server_ssl); + if (ret == 0 && wolfSSL_is_init_finished(server_ssl)) + break; + } + + if (ret == 0) + showPeerEx(server_ssl, 0); + + /* Receive HTTP request */ + if (ret == 0) + ret = wolfssl_recv(server_ssl); + /* Send HTTP response */ + if (ret == 0) + ret = wolfssl_send(server_ssl, msgHTTPIndex); + + if (server_ssl != NULL) + wolfSSL_free(server_ssl); + + if (clientfd != WOLFSSL_SOCKET_INVALID) + CloseSocket(clientfd); + } + while (ret == 0); + + return ret; +} + +/* Main entry point. */ +int main(int argc, char* argv[]) +{ + int ret = 0; + WOLFSSL_CTX* server_ctx = NULL; + SOCKET_T sockfd = WOLFSSL_SOCKET_INVALID; + +#if defined(DEBUG_WOLFSSL) + wolfSSL_Debugging_ON(); +#endif + /* Initialise wolfSSL library */ + wolfSSL_Init(); + + ret = wolfssl_server_ctx_new(&server_ctx); + if (ret == 0) + ret = wolfssl_server_listen_tcp(&sockfd); + + /* Do server */ + ret = server(server_ctx, sockfd); + + if (server_ctx != NULL) + wolfSSL_CTX_free(server_ctx); + if (sockfd != WOLFSSL_SOCKET_INVALID) + CloseSocket(sockfd); + + /* Cleanup wolfSSL library */ + wolfSSL_Cleanup(); + + if (ret == 0) + printf("Done\n"); + else { + char buffer[80]; + printf("Error: %d, %s\n", ret, wolfSSL_ERR_error_string(ret, buffer)); + } + + return (ret == 0) ? 0 : 1; +} + diff --git a/embedded/tls-sock-server.c b/embedded/tls-sock-server.c new file mode 100644 index 00000000..3358d26e --- /dev/null +++ b/embedded/tls-sock-server.c @@ -0,0 +1,284 @@ +/* tls-sock-server.c + * + * Copyright (C) 2006-2019 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 + */ + +#includewolfSSL has successfully performed handshake!
\n" + "\n" + "\n"; + + +/* Create a new wolfSSL CTX server with a certificate for authentication. */ +static int wolfssl_server_ctx_new(WOLFSSL_CTX** ctx) +{ + int ret = 0; + WOLFSSL_CTX* server_ctx = NULL; + + /* Create and initialize WOLFSSL_CTX */ + if ((server_ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())) == NULL) { + printf("ERROR: failed to create WOLFSSL_CTX\n"); + ret = -1; + } + + if (ret == 0) { + /* Load client certificates into WOLFSSL_CTX */ + if (wolfSSL_CTX_use_certificate_buffer(server_ctx, SERVER_CERT, + SERVER_CERT_LEN, WOLFSSL_FILETYPE_ASN1) != WOLFSSL_SUCCESS) { + printf("ERROR: failed to load server certificate\n"); + ret = -1; + } + } + + if (ret == 0) { + /* Load client certificates into WOLFSSL_CTX */ + if (wolfSSL_CTX_use_PrivateKey_buffer(server_ctx, SERVER_KEY, + SERVER_KEY_LEN, WOLFSSL_FILETYPE_ASN1) != WOLFSSL_SUCCESS) { + printf("ERROR: failed to load server key\n"); + ret = -1; + } + } + + if (ret == 0) { + /* Return newly created wolfSSL context */ + *ctx = server_ctx; + } + else { + if (server_ctx != NULL) + wolfSSL_CTX_free(server_ctx); + } + return ret; +} + +/* Create a new wolfSSL server with a certificate for authentication. */ +static int wolfssl_server_ssl_new(WOLFSSL_CTX* ctx, WOLFSSL** ssl) +{ + int ret = 0; + WOLFSSL* server_ssl = NULL; + + if (ret == 0) { + /* Create a WOLFSSL object */ + if ((server_ssl = wolfSSL_new(ctx)) == NULL) { + printf("ERROR: failed to create WOLFSSL object\n"); + ret = -1; + } + } + + if (ret == 0) { + /* make wolfSSL object nonblocking */ + wolfSSL_set_using_nonblock(server_ssl, 1); + } + + if (ret == 0) { + /* Return newly created wolfSSL context and object */ + *ssl = server_ssl; + } + else { + if (server_ssl != NULL) + wolfSSL_free(server_ssl); + } + + return ret; +} + +/* Server accepting a client using TLS */ +static int wolfssl_server_accept(WOLFSSL* ssl) +{ + int ret = 0; + + if (wolfSSL_accept(ssl) != WOLFSSL_SUCCESS) { + ret = wolfSSL_get_error(ssl, 0); + if (ret == WOLFSSL_ERROR_WANT_READ) + ret = 0; + else if (ret > 0) + ret = -1; + } + + return ret; +} + + +/* Send application data. */ +static int wolfssl_send(WOLFSSL* ssl, const char* msg) +{ + int ret = 0; + int len; + + printf("Sending:\n%s\n", msg); + len = wolfSSL_write(ssl, msg, XSTRLEN(msg)); + if (len < 0) + ret = len; + else if (len != XSTRLEN(msg)) + ret = -1; + + return ret; +} + +/* Receive application data. */ +static int wolfssl_recv(WOLFSSL* ssl) +{ + int ret; + int err = 0; + byte reply[80]; + int total = 0; + + printf("Receive:\n"); + do { + ret = wolfSSL_read(ssl, reply, sizeof(reply)-1); + if (ret > 0) { + reply[ret] = '\0'; + printf("%s", reply); + total += ret; + err = 0; + } + else if (ret == -1) + err = wolfSSL_get_error(ssl, 0); + } + while (err == 0 || (total == 0 && err == WOLFSSL_ERROR_WANT_READ)); + + if (total > 0 && err == WOLFSSL_ERROR_WANT_READ) + ret = 0; + + return ret; +} + +/* Establish a socket to listen on. */ +static int wolfssl_server_listen_tcp(SOCKET_T* fd) +{ + word16 port = wolfSSLPort; + + return tcp_listen(fd, &port, 1, 0, 0); +} + +/* Accept the TCP connection from the client. */ +static int wolfssl_server_accept_tcp(WOLFSSL* ssl, SOCKET_T fd, + SOCKET_T* acceptfd) +{ + int ret = 0; + SOCKET_T clientfd = WOLFSSL_SOCKET_INVALID; + + ret = tcp_accept(&fd, &clientfd); + if (ret == 0) { + *acceptfd = clientfd; + ret = tcp_set_nonblocking(&clientfd); + } + + if (ret == 0) { + if (wolfSSL_set_fd(ssl, clientfd) != WOLFSSL_SUCCESS) + ret = -1; + } + + return ret; +} + + +/* Server operations. */ +static int server(WOLFSSL_CTX* server_ctx, SOCKET_T sockfd) +{ + int ret; + WOLFSSL* server_ssl = NULL; + SOCKET_T clientfd = WOLFSSL_SOCKET_INVALID; + + do { + ret = wolfssl_server_ssl_new(server_ctx, &server_ssl); + if (ret == 0) + ret = wolfssl_server_accept_tcp(server_ssl, sockfd, &clientfd); + + while (ret == 0) { + ret = wolfssl_server_accept(server_ssl); + if (ret == 0 && wolfSSL_is_init_finished(server_ssl)) + break; + } + + if (ret == 0) + showPeerEx(server_ssl, 0); + + /* Receive HTTP request */ + if (ret == 0) + ret = wolfssl_recv(server_ssl); + /* Send HTTP response */ + if (ret == 0) + ret = wolfssl_send(server_ssl, msgHTTPIndex); + + if (server_ssl != NULL) + wolfSSL_free(server_ssl); + + if (clientfd != WOLFSSL_SOCKET_INVALID) + CloseSocket(clientfd); + } + while (ret == 0); + + return ret; +} + +/* Main entry point. */ +int main(int argc, char* argv[]) +{ + int ret = 0; + WOLFSSL_CTX* server_ctx = NULL; + SOCKET_T sockfd = WOLFSSL_SOCKET_INVALID; + +#if defined(DEBUG_WOLFSSL) + wolfSSL_Debugging_ON(); +#endif + /* Initialise wolfSSL library */ + wolfSSL_Init(); + + ret = wolfssl_server_ctx_new(&server_ctx); + if (ret == 0) + ret = wolfssl_server_listen_tcp(&sockfd); + + /* Do server */ + ret = server(server_ctx, sockfd); + + if (server_ctx != NULL) + wolfSSL_CTX_free(server_ctx); + if (sockfd != WOLFSSL_SOCKET_INVALID) + CloseSocket(sockfd); + + /* Cleanup wolfSSL library */ + wolfSSL_Cleanup(); + + if (ret == 0) + printf("Done\n"); + else { + char buffer[80]; + printf("Error: %d, %s\n", ret, wolfSSL_ERR_error_string(ret, buffer)); + } + + return (ret == 0) ? 0 : 1; +} + diff --git a/embedded/tls-sock-threaded.c b/embedded/tls-sock-threaded.c new file mode 100644 index 00000000..1f4aaa55 --- /dev/null +++ b/embedded/tls-sock-threaded.c @@ -0,0 +1,468 @@ +/* tls-sock-threaded.c + * + * Copyright (C) 2006-2019 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 + */ + +#includewolfSSL has successfully performed handshake!
\n" + "\n" + "\n"; + + +/* Create a new wolfSSL client with a server CA certificate. */ +static int wolfssl_client_new(WOLFSSL_CTX** ctx, WOLFSSL** ssl) +{ + int ret = 0; + WOLFSSL_CTX* client_ctx = NULL; + WOLFSSL* client_ssl = NULL; + + /* Create and initialize WOLFSSL_CTX */ + if ((client_ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())) == NULL) { + printf("ERROR: failed to create WOLFSSL_CTX\n"); + ret = -1; + } + + if (ret == 0) { + /* Load client certificates into WOLFSSL_CTX */ + if (wolfSSL_CTX_load_verify_buffer(client_ctx, CA_CERTS, CA_CERTS_LEN, + WOLFSSL_FILETYPE_ASN1) != WOLFSSL_SUCCESS) { + printf("ERROR: failed to load CA certificate\n"); + ret = -1; + } + } + + if (ret == 0) { + /* Create a WOLFSSL object */ + if ((client_ssl = wolfSSL_new(client_ctx)) == NULL) { + printf("ERROR: failed to create WOLFSSL object\n"); + ret = -1; + } + } + + if (ret == 0) { + /* make wolfSSL object nonblocking */ + wolfSSL_set_using_nonblock(client_ssl, 1); + } + + if (ret == 0) { + /* Return newly created wolfSSL context and object */ + *ctx = client_ctx; + *ssl = client_ssl; + } + else { + if (client_ssl != NULL) + wolfSSL_free(client_ssl); + if (client_ctx != NULL) + wolfSSL_CTX_free(client_ctx); + } + + return ret; +} + +/* Client connecting to server using TLS */ +static int wolfssl_client_connect(WOLFSSL* ssl) +{ + int ret = 0; + + if (wolfSSL_connect(ssl) != WOLFSSL_SUCCESS) { + ret = wolfSSL_get_error(ssl, 0); + if (ret == WOLFSSL_ERROR_WANT_READ) + ret = 0; + else if (ret > 0) + ret = -1; + } + + return ret; +} + + + +/* Create a new wolfSSL server with a certificate for authentication. */ +static int wolfssl_server_new(WOLFSSL_CTX** ctx, WOLFSSL** ssl) +{ + int ret = 0; + WOLFSSL_CTX* server_ctx = NULL; + WOLFSSL* server_ssl = NULL; + + /* Create and initialize WOLFSSL_CTX */ + if ((server_ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())) == NULL) { + printf("ERROR: failed to create WOLFSSL_CTX\n"); + ret = -1; + } + + if (ret == 0) { + /* Load client certificates into WOLFSSL_CTX */ + if (wolfSSL_CTX_use_certificate_buffer(server_ctx, SERVER_CERT, + SERVER_CERT_LEN, WOLFSSL_FILETYPE_ASN1) != WOLFSSL_SUCCESS) { + printf("ERROR: failed to load server certificate\n"); + ret = -1; + } + } + + if (ret == 0) { + /* Load client certificates into WOLFSSL_CTX */ + if (wolfSSL_CTX_use_PrivateKey_buffer(server_ctx, SERVER_KEY, + SERVER_KEY_LEN, WOLFSSL_FILETYPE_ASN1) != WOLFSSL_SUCCESS) { + printf("ERROR: failed to load server key\n"); + ret = -1; + } + } + + if (ret == 0) { + /* Create a WOLFSSL object */ + if ((server_ssl = wolfSSL_new(server_ctx)) == NULL) { + printf("ERROR: failed to create WOLFSSL object\n"); + ret = -1; + } + } + + if (ret == 0) { + /* make wolfSSL object nonblocking */ + wolfSSL_set_using_nonblock(server_ssl, 1); + } + + if (ret == 0) { + /* Return newly created wolfSSL context and object */ + *ctx = server_ctx; + *ssl = server_ssl; + } + else { + if (server_ssl != NULL) + wolfSSL_free(server_ssl); + if (server_ctx != NULL) + wolfSSL_CTX_free(server_ctx); + } + + return ret; +} + +/* Server accepting a client using TLS */ +static int wolfssl_server_accept(WOLFSSL* ssl) +{ + int ret = 0; + + if (wolfSSL_accept(ssl) != WOLFSSL_SUCCESS) { + ret = wolfSSL_get_error(ssl, 0); + if (ret == WOLFSSL_ERROR_WANT_READ) + ret = 0; + else if (ret > 0) + ret = -1; + } + + return ret; +} + + +/* Send application data. */ +static int wolfssl_send(WOLFSSL* ssl, const char* msg) +{ + int ret = 0; + int len; + + printf("Sending:\n%s\n", msg); + len = wolfSSL_write(ssl, msg, XSTRLEN(msg)); + if (len < 0) + ret = len; + else if (len != XSTRLEN(msg)) + ret = -1; + + return ret; +} + +/* Receive application data. */ +static int wolfssl_recv(WOLFSSL* ssl) +{ + int ret; + byte reply[256]; + + ret = wolfSSL_read(ssl, reply, sizeof(reply)-1); + if (ret > 0) { + reply[ret] = '\0'; + printf("Received:\n%s\n", reply); + ret = 1; + } + else if (wolfSSL_want_read(ssl) || wolfSSL_want_write(ssl)) + ret = 0; + + return ret; +} + + +/* Free the WOLFSSL object and context. */ +static void wolfssl_free(WOLFSSL_CTX* ctx, WOLFSSL* ssl) +{ + if (ssl != NULL) + wolfSSL_free(ssl); + if (ctx != NULL) + wolfSSL_CTX_free(ctx); +} + + + +/* Start the server thread. */ +static void start_thread(THREAD_FUNC func, func_args* args, THREAD_TYPE* thread) +{ +#if defined(_POSIX_THREADS) && !defined(__MINGW32__) + pthread_create(thread, 0, func, args); +#elif defined(WOLFSSL_TIRTOS) + /* Initialize the defaults and set the parameters. */ + Task_Params taskParams; + Task_Params_init(&taskParams); + taskParams.arg0 = (UArg)args; + taskParams.stackSize = 24*1024; + *thread = Task_create((Task_FuncPtr)func, &taskParams, NULL); + if (*thread == NULL) { + printf("Failed to create new Task\n"); + } + Task_yield(); +#elif defined(USE_WINDOWS_API) + *thread = (THREAD_TYPE)_beginthreadex(0, 0, func, args, 0, 0); +#endif +} + +static void join_thread(THREAD_TYPE thread) +{ +#if defined(_POSIX_THREADS) && !defined(__MINGW32__) + pthread_join(thread, 0); +#elif defined(WOLFSSL_TIRTOS) + while (1) { + if (Task_getMode(thread) == Task_Mode_TERMINATED) { + Task_sleep(5); + break; + } + Task_yield(); + } +#elif defined(USE_WINDOWS_API) + WaitForSingleObject((HANDLE)thread, INFINITE); + CloseHandle((HANDLE)thread); +#endif +} + + +/* Accept the TCP connection from the client. */ +int wolfssl_server_accept_tcp(WOLFSSL* ssl, SOCKET_T* fd, SOCKET_T* acceptfd) +{ + int ret = 0; + SOCKET_T sockfd = WOLFSSL_SOCKET_INVALID; + SOCKET_T clientfd = WOLFSSL_SOCKET_INVALID; + word16 port = wolfSSLPort; + + ret = tcp_listen(&sockfd, &port, 1, 0, 0); + + wc_UnLockMutex(&server_mutex); + + if (ret == 0) + ret = tcp_accept(&sockfd, &clientfd); + if (ret == 0) { + *acceptfd = clientfd; + ret = tcp_set_nonblocking(&clientfd); + } + + if (ret == 0) { + printf("Server has accepted client\n"); + if (wolfSSL_set_fd(ssl, clientfd) != WOLFSSL_SUCCESS) + ret = -1; + } + + return ret; +} + + +/* Thread to do the server operations. */ +static THREAD_RETURN WOLFSSL_THREAD server_thread(void* args) +{ + int ret = 0; + WOLFSSL_CTX* server_ctx = NULL; + WOLFSSL* server_ssl = NULL; + SOCKET_T sockfd = WOLFSSL_SOCKET_INVALID; + SOCKET_T clientfd = WOLFSSL_SOCKET_INVALID; + + + if (ret == 0) + ret = wolfssl_server_new(&server_ctx, &server_ssl); + + if (ret == 0) + ret = wolfssl_server_accept_tcp(server_ssl, &sockfd, &clientfd); + + while (ret == 0) { + ret = wolfssl_server_accept(server_ssl); + if (ret == 0 && wolfSSL_is_init_finished(server_ssl)) + break; + } + + /* Receive HTTP request */ + while (ret == 0) { + ret = wolfssl_recv(server_ssl); + } + if (ret == 1) + ret = 0; + /* Send HTTP response */ + if (ret == 0) + ret = wolfssl_send(server_ssl, msgHTTPIndex); + + printf("Server Return: %d\n", ret); + + wolfssl_free(server_ctx, server_ssl); + + if (clientfd != WOLFSSL_SOCKET_INVALID) + CloseSocket(clientfd); + if (sockfd != WOLFSSL_SOCKET_INVALID) + CloseSocket(sockfd); + +#if defined(HAVE_ECC) && defined(FP_ECC) + wc_ecc_fp_free(); /* free per thread cache */ +#endif + +#ifndef WOLFSSL_TIRTOS + return 0; +#endif +} + +/* TCP connect to the server. */ +int wolfssl_client_connect_tcp(WOLFSSL* ssl, SOCKET_T* fd) +{ + int ret = 0; + + ret = tcp_connect(fd, wolfSSLIP, wolfSSLPort, 0, 0, ssl); + if (ret == 0) + ret = tcp_set_nonblocking(fd); + + if (ret == 0) { + printf("Client has connected to server\n"); + if (wolfSSL_set_fd(ssl, *fd) != WOLFSSL_SUCCESS) + ret = -1; + } + + return ret; +} + +/* Client connection operations */ +static int client() +{ + int ret = 0; + WOLFSSL_CTX* client_ctx = NULL; + WOLFSSL* client_ssl = NULL; + SOCKET_T sockfd = WOLFSSL_SOCKET_INVALID; + + /* Create a new client connection */ + ret = wolfssl_client_new(&client_ctx, &client_ssl); + + if (ret == 0) + wolfssl_client_connect_tcp(client_ssl, &sockfd); + + /* Keep trying to connect until handshake finished */ + while (ret == 0) { + ret = wolfssl_client_connect(client_ssl); + if (ret == 0 && wolfSSL_is_init_finished(client_ssl)) + break; + } + if (ret == 0) + printf("Handshake complete\n"); + + /* Send HTTP request */ + if (ret == 0) + ret = wolfssl_send(client_ssl, msgHTTPGet); + /* Receive HTTP response */ + while (ret == 0) + ret = wolfssl_recv(client_ssl); + if (ret == 1) + ret = 0; + + printf("Client Return: %d\n", ret); + + /* Free client connection data */ + wolfssl_free(client_ctx, client_ssl); + + if (sockfd != WOLFSSL_SOCKET_INVALID) + CloseSocket(sockfd); + + return ret; +} + +int main(int argc, char* argv[]) +{ + int ret = 0; + THREAD_TYPE serverThread; + +#if defined(DEBUG_WOLFSSL) + wolfSSL_Debugging_ON(); +#endif + /* Initialise wolfSSL library */ + wolfSSL_Init(); + + /* Initialise mutex that synchronises when server is ready for client */ + wc_InitMutex(&server_mutex); + + /* Unlocked by server thread */ + wc_LockMutex(&server_mutex); + + /* Start server */ + start_thread(server_thread, NULL, &serverThread); + + /* Wait for server to be ready */ + wc_LockMutex(&server_mutex); + wc_UnLockMutex(&server_mutex); + + /* Do client */ + client(); + + /* Cleanup finished thread */ + join_thread(serverThread); + + /* Cleanup wolfSSL library */ + wolfSSL_Cleanup(); + + printf("Done\n"); + + return (ret == 0) ? 0 : 1; +} + +#else + +int main(int argc, char* argv[]) +{ + printf("Threading required - compile wolfSSL without SINGLE_THREAED\n"); + return 0; +} + +#endif + diff --git a/embedded/tls-threaded.c b/embedded/tls-threaded.c new file mode 100644 index 00000000..00c3c19a --- /dev/null +++ b/embedded/tls-threaded.c @@ -0,0 +1,494 @@ +/* tls-threaded.c + * + * Copyright (C) 2006-2019 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 + */ + +#includewolfSSL has successfully performed handshake!
\n" + "\n" + "\n"; + + +/* wolfSSL client wants to read data from the server. */ +static int recv_client(WOLFSSL* ssl, char* buff, int sz, void* ctx) +{ + wc_LockMutex(&client_mutex); + if (client_buffer_sz > 0) { + /* Take as many bytes is available or requested from buffer. */ + if (sz > client_buffer_sz) + sz = client_buffer_sz; + XMEMCPY(buff, client_buffer, sz); + if (sz < client_buffer_sz) { + XMEMMOVE(client_buffer, client_buffer + sz, client_buffer_sz - sz); + } + client_buffer_sz -= sz; + } + else + sz = WOLFSSL_CBIO_ERR_WANT_READ; + wc_UnLockMutex(&client_mutex); + + return sz; +} + +/* wolfSSL client wants to write data to the server. */ +static int send_client(WOLFSSL* ssl, char* buff, int sz, void* ctx) +{ + wc_LockMutex(&server_mutex); + if (server_buffer_sz < BUFFER_SIZE) + { + /* Put in as many bytes requested or will fit in buffer. */ + if (sz > BUFFER_SIZE - server_buffer_sz) + sz = BUFFER_SIZE - server_buffer_sz; + XMEMCPY(server_buffer + server_buffer_sz, buff, sz); + server_buffer_sz += sz; + } + else + sz = WOLFSSL_CBIO_ERR_WANT_WRITE; + wc_UnLockMutex(&server_mutex); + + return sz; +} + +/* wolfSSL server wants to read data from the client. */ +static int recv_server(WOLFSSL* ssl, char* buff, int sz, void* ctx) +{ + wc_LockMutex(&server_mutex); + if (server_buffer_sz > 0) { + /* Take as many bytes is available or requested from buffer. */ + if (sz > server_buffer_sz) + sz = server_buffer_sz; + XMEMCPY(buff, server_buffer, sz); + if (sz < server_buffer_sz) { + XMEMMOVE(server_buffer, server_buffer + sz, server_buffer_sz - sz); + } + server_buffer_sz -= sz; + } + else + sz = WOLFSSL_CBIO_ERR_WANT_READ; + wc_UnLockMutex(&server_mutex); + + return sz; +} + +/* wolfSSL server wants to write data to the client. */ +static int send_server(WOLFSSL* ssl, char* buff, int sz, void* ctx) +{ + wc_LockMutex(&client_mutex); + if (client_buffer_sz < BUFFER_SIZE) + { + /* Put in as many bytes requested or will fit in buffer. */ + if (sz > BUFFER_SIZE - client_buffer_sz) + sz = BUFFER_SIZE - client_buffer_sz; + XMEMCPY(client_buffer + client_buffer_sz, buff, sz); + client_buffer_sz += sz; + } + else + sz = WOLFSSL_CBIO_ERR_WANT_WRITE; + wc_UnLockMutex(&client_mutex); + + return sz; +} + +/* Create a new wolfSSL client with a server CA certificate. */ +static int wolfssl_client_new(WOLFSSL_CTX** ctx, WOLFSSL** ssl) +{ + int ret = 0; + WOLFSSL_CTX* client_ctx = NULL; + WOLFSSL* client_ssl = NULL; + + /* Create and initialize WOLFSSL_CTX */ + if ((client_ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())) == NULL) { + printf("ERROR: failed to create WOLFSSL_CTX\n"); + ret = -1; + } + + if (ret == 0) { + /* Load client certificates into WOLFSSL_CTX */ + if (wolfSSL_CTX_load_verify_buffer(client_ctx, CA_CERTS, CA_CERTS_LEN, + WOLFSSL_FILETYPE_ASN1) != WOLFSSL_SUCCESS) { + printf("ERROR: failed to load CA certificate\n"); + ret = -1; + } + } + + if (ret == 0) { + /* Register callbacks */ + wolfSSL_SetIORecv(client_ctx, recv_client); + wolfSSL_SetIOSend(client_ctx, send_client); + } + + if (ret == 0) { + /* Create a WOLFSSL object */ + if ((client_ssl = wolfSSL_new(client_ctx)) == NULL) { + printf("ERROR: failed to create WOLFSSL object\n"); + ret = -1; + } + } + + if (ret == 0) { + /* make wolfSSL object nonblocking */ + wolfSSL_set_using_nonblock(client_ssl, 1); + } + + if (ret == 0) { + /* Return newly created wolfSSL context and object */ + *ctx = client_ctx; + *ssl = client_ssl; + } + else { + if (client_ssl != NULL) + wolfSSL_free(client_ssl); + if (client_ctx != NULL) + wolfSSL_CTX_free(client_ctx); + } + + return ret; +} + +/* Client connecting to server using TLS */ +static int wolfssl_client_connect(WOLFSSL* ssl) +{ + int ret = 0; + + if (wolfSSL_connect(ssl) != WOLFSSL_SUCCESS) { + if (!wolfSSL_want_read(ssl) && !wolfSSL_want_write(ssl)) + ret = -1; + } + + return ret; +} + + + +/* Create a new wolfSSL server with a certificate for authentication. */ +static int wolfssl_server_new(WOLFSSL_CTX** ctx, WOLFSSL** ssl) +{ + int ret = 0; + WOLFSSL_CTX* server_ctx = NULL; + WOLFSSL* server_ssl = NULL; + + /* Create and initialize WOLFSSL_CTX */ + if ((server_ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())) == NULL) { + printf("ERROR: failed to create WOLFSSL_CTX\n"); + ret = -1; + } + + if (ret == 0) { + /* Load client certificates into WOLFSSL_CTX */ + if (wolfSSL_CTX_use_certificate_buffer(server_ctx, SERVER_CERT, + SERVER_CERT_LEN, WOLFSSL_FILETYPE_ASN1) != WOLFSSL_SUCCESS) { + printf("ERROR: failed to load server certificate\n"); + ret = -1; + } + } + + if (ret == 0) { + /* Load client certificates into WOLFSSL_CTX */ + if (wolfSSL_CTX_use_PrivateKey_buffer(server_ctx, SERVER_KEY, + SERVER_KEY_LEN, WOLFSSL_FILETYPE_ASN1) != WOLFSSL_SUCCESS) { + printf("ERROR: failed to load server key\n"); + ret = -1; + } + } + + if (ret == 0) { + /* Register callbacks */ + wolfSSL_SetIORecv(server_ctx, recv_server); + wolfSSL_SetIOSend(server_ctx, send_server); + } + + if (ret == 0) { + /* Create a WOLFSSL object */ + if ((server_ssl = wolfSSL_new(server_ctx)) == NULL) { + printf("ERROR: failed to create WOLFSSL object\n"); + ret = -1; + } + } + + if (ret == 0) { + /* make wolfSSL object nonblocking */ + wolfSSL_set_using_nonblock(server_ssl, 1); + } + + if (ret == 0) { + /* Return newly created wolfSSL context and object */ + *ctx = server_ctx; + *ssl = server_ssl; + } + else { + if (server_ssl != NULL) + wolfSSL_free(server_ssl); + if (server_ctx != NULL) + wolfSSL_CTX_free(server_ctx); + } + + return ret; +} + +/* Server accepting a client using TLS */ +static int wolfssl_server_accept(WOLFSSL* ssl) +{ + int ret = 0; + + if (wolfSSL_accept(ssl) != WOLFSSL_SUCCESS) { + if (!wolfSSL_want_read(ssl) && !wolfSSL_want_write(ssl)) + ret = -1; + } + + return ret; +} + + +/* Send application data. */ +static int wolfssl_send(WOLFSSL* ssl, const char* msg) +{ + int ret = 0; + int len; + + printf("Sending:\n%s\n", msg); + len = wolfSSL_write(ssl, msg, XSTRLEN(msg)); + if (len < 0) + ret = len; + else if (len != XSTRLEN(msg)) + ret = -1; + + return ret; +} + +/* Receive application data. */ +static int wolfssl_recv(WOLFSSL* ssl) +{ + int ret; + byte reply[256]; + + ret = wolfSSL_read(ssl, reply, sizeof(reply)-1); + if (ret > 0) { + reply[ret] = '\0'; + printf("Received:\n%s\n", reply); + ret = 1; + } + else if (wolfSSL_want_read(ssl) || wolfSSL_want_write(ssl)) + ret = 0; + + return ret; +} + + +/* Free the WOLFSSL object and context. */ +static void wolfssl_free(WOLFSSL_CTX* ctx, WOLFSSL* ssl) +{ + if (ssl != NULL) + wolfSSL_free(ssl); + if (ctx != NULL) + wolfSSL_CTX_free(ctx); +} + + + +/* Start the server thread. */ +static void start_thread(THREAD_FUNC func, func_args* args, THREAD_TYPE* thread) +{ +#if defined(_POSIX_THREADS) && !defined(__MINGW32__) + pthread_create(thread, 0, func, args); +#elif defined(WOLFSSL_TIRTOS) + /* Initialize the defaults and set the parameters. */ + Task_Params taskParams; + Task_Params_init(&taskParams); + taskParams.arg0 = (UArg)args; + taskParams.stackSize = 24*1024; + *thread = Task_create((Task_FuncPtr)func, &taskParams, NULL); + if (*thread == NULL) { + printf("Failed to create new Task\n"); + } + Task_yield(); +#elif defined(USE_WINDOWS_API) + *thread = (THREAD_TYPE)_beginthreadex(0, 0, func, args, 0, 0); +#endif +} + +static void join_thread(THREAD_TYPE thread) +{ +#if defined(_POSIX_THREADS) && !defined(__MINGW32__) + pthread_join(thread, 0); +#elif defined(WOLFSSL_TIRTOS) + while(1) { + if (Task_getMode(thread) == Task_Mode_TERMINATED) { + Task_sleep(5); + break; + } + Task_yield(); + } +#elif defined(USE_WINDOWS_API) + WaitForSingleObject((HANDLE)thread, INFINITE); + CloseHandle((HANDLE)thread); +#endif +} + + +/* Thread to do the server operations. */ +static THREAD_RETURN WOLFSSL_THREAD server_thread(void* args) +{ + int ret = 0; + WOLFSSL_CTX* server_ctx = NULL; + WOLFSSL* server_ssl = NULL; + + + if (ret == 0) + ret = wolfssl_server_new(&server_ctx, &server_ssl); + + while (ret == 0) { + ret = wolfssl_server_accept(server_ssl); + if (ret == 0 && wolfSSL_is_init_finished(server_ssl)) + break; + } + + /* Receive HTTP request */ + while (ret == 0) { + ret = wolfssl_recv(server_ssl); + } + if (ret == 1) + ret = 0; + /* Send HTTP response */ + if (ret == 0) + ret = wolfssl_send(server_ssl, msgHTTPIndex); + + printf("Server Return: %d\n", ret); + + wolfssl_free(server_ctx, server_ssl); + +#if defined(HAVE_ECC) && defined(FP_ECC) + wc_ecc_fp_free(); /* free per thread cache */ +#endif + +#ifndef WOLFSSL_TIRTOS + return 0; +#endif +} + +/* Client connection operations */ +static int client() +{ + int ret = 0; + WOLFSSL_CTX* client_ctx = NULL; + WOLFSSL* client_ssl = NULL; + + /* Create a new client connection */ + ret = wolfssl_client_new(&client_ctx, &client_ssl); + + /* Keep trying to connect until handshake finished */ + while (ret == 0) { + ret = wolfssl_client_connect(client_ssl); + if (ret == 0 && wolfSSL_is_init_finished(client_ssl)) + break; + } + if (ret == 0) + printf("Handshake complete\n"); + + /* Send HTTP request */ + if (ret == 0) + ret = wolfssl_send(client_ssl, msgHTTPGet); + /* Receive HTTP response */ + while (ret == 0) + ret = wolfssl_recv(client_ssl); + if (ret == 1) + ret = 0; + + printf("Client Return: %d\n", ret); + + /* Free client connection data */ + wolfssl_free(client_ctx, client_ssl); + + return ret; +} + +int main(int argc, char* argv[]) +{ + int ret = 0; + THREAD_TYPE serverThread; + +#if defined(DEBUG_WOLFSSL) + wolfSSL_Debugging_ON(); +#endif + /* Initialise wolfSSL library */ + wolfSSL_Init(); + + /* Initialise mutexs protecting I/O buffers */ + wc_InitMutex(&client_mutex); + wc_InitMutex(&server_mutex); + + /* Start server */ + start_thread(server_thread, NULL, &serverThread); + /* Do client */ + client(); + /* Cleanup finished thread */ + join_thread(serverThread); + + /* Cleanup wolfSSL library */ + wolfSSL_Cleanup(); + + printf("Done\n"); + + return (ret == 0) ? 0 : 1; +} + +#else + +int main(int argc, char* argv[]) +{ + printf("Requires threading - compile wolfssl without SINGLE_THREADED\n"); + return 0; +} + +#endif