From 7ed94abe134992ad0519f46fa67b40b3d623628a Mon Sep 17 00:00:00 2001 From: Sean Parkinson Date: Fri, 22 Feb 2019 15:39:19 +1000 Subject: [PATCH] Add some samples for embedded use/testing --- .gitignore | 8 + embedded/Makefile | 102 ++++++ embedded/certs.h | 62 ++++ embedded/sockets.h | 605 ++++++++++++++++++++++++++++++++++ embedded/threading.h | 62 ++++ embedded/tls-client-server.c | 480 +++++++++++++++++++++++++++ embedded/tls-info.h | 232 +++++++++++++ embedded/tls-sock-client-ca.c | 261 +++++++++++++++ embedded/tls-sock-client.c | 241 ++++++++++++++ embedded/tls-sock-server-ca.c | 298 +++++++++++++++++ embedded/tls-sock-server.c | 284 ++++++++++++++++ embedded/tls-sock-threaded.c | 468 ++++++++++++++++++++++++++ embedded/tls-threaded.c | 494 +++++++++++++++++++++++++++ 13 files changed, 3597 insertions(+) create mode 100644 embedded/Makefile create mode 100644 embedded/certs.h create mode 100644 embedded/sockets.h create mode 100644 embedded/threading.h create mode 100644 embedded/tls-client-server.c create mode 100644 embedded/tls-info.h create mode 100644 embedded/tls-sock-client-ca.c create mode 100644 embedded/tls-sock-client.c create mode 100644 embedded/tls-sock-server-ca.c create mode 100644 embedded/tls-sock-server.c create mode 100644 embedded/tls-sock-threaded.c create mode 100644 embedded/tls-threaded.c 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/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 + +#include + diff --git a/embedded/sockets.h b/embedded/sockets.h new file mode 100644 index 00000000..ba32c370 --- /dev/null +++ b/embedded/sockets.h @@ -0,0 +1,605 @@ +/* sockets.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 + */ + + +#ifdef USE_WINDOWS_API + #include + #ifdef TEST_IPV6 /* don't require newer SDK for IPV4 */ + #include + #include + #endif + #define SOCKET_T SOCKET + #define SNPRINTF _snprintf +#elif defined(WOLFSSL_MDK_ARM) || defined(WOLFSSL_KEIL_TCP_NET) + #include + #include "rl_net.h" + #define SOCKET_T int + typedef int socklen_t ; + static unsigned long inet_addr(const char *cp) + { + unsigned int a[4] ; unsigned long ret ; + sscanf(cp, "%d.%d.%d.%d", &a[0], &a[1], &a[2], &a[3]) ; + ret = ((a[3]<<24) + (a[2]<<16) + (a[1]<<8) + a[0]) ; + return(ret) ; + } + #if defined(HAVE_KEIL_RTX) + #define sleep(t) os_dly_wait(t/1000+1) ; + #elif defined (WOLFSSL_CMSIS_RTOS) + #define sleep(t) osDelay(t/1000+1) ; + #endif +#elif defined(WOLFSSL_TIRTOS) + #include + #include + #include + #include + #include + #include + struct hostent { + char *h_name; /* official name of host */ + char **h_aliases; /* alias list */ + int h_addrtype; /* host address type */ + int h_length; /* length of address */ + char **h_addr_list; /* list of addresses from name server */ + }; + #define SOCKET_T int +#elif defined(WOLFSSL_VXWORKS) + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #define SOCKET_T int +#elif defined(WOLFSSL_ZEPHYR) + #include + #include + #include + #define SOCKET_T int + #define SOL_SOCKET 1 + #define SO_REUSEADDR 201 + #define WOLFSSL_USE_GETADDRINFO + + static unsigned long inet_addr(const char *cp) + { + unsigned int a[4]; unsigned long ret; + int i, j; + for (i=0, j=0; i<4; i++) { + a[i] = 0; + while (cp[j] != '.' && cp[j] != '\0') { + a[i] *= 10; + a[i] += cp[j] - '0'; + j++; + } + } + ret = ((a[3]<<24) + (a[2]<<16) + (a[1]<<8) + a[0]) ; + return(ret) ; + } +#else + #include + #include +#ifndef WOLFSSL_LEANPSK + #include + #include + #include + #include + #include + #include + #include + #include + #include + #ifdef TEST_IPV6 + #include + #endif +#endif + #define SOCKET_T int + #ifndef SO_NOSIGPIPE + #include /* ignore SIGPIPE */ + #endif + #define SNPRINTF snprintf +#endif /* USE_WINDOWS_API */ + + +#ifdef WOLFSSL_KEIL_TCP_NET + #define SOCK_LISTEN_MAX_QUEUE 1 +#else + #define SOCK_LISTEN_MAX_QUEUE 5 +#endif + + +#ifndef WOLFSSL_SOCKET_INVALID + #ifdef USE_WINDOWS_API + #define WOLFSSL_SOCKET_INVALID ((SOCKET_T)INVALID_SOCKET) + #define WOLFSSL_SOCKET_IS_INVALID(s) \ + ((SOCKET_T)(s) == WOLFSSL_SOCKET_INVALID) + #elif defined(WOLFSSL_TIRTOS) + #define WOLFSSL_SOCKET_INVALID ((SOCKET_T)-1) + #define WOLFSSL_SOCKET_IS_INVALID(s) \ + ((SOCKET_T)(s) == WOLFSSL_SOCKET_INVALID) + #else + #define WOLFSSL_SOCKET_INVALID (SOCKET_T)(0) + #define WOLFSSL_SOCKET_IS_INVALID(s) \ + ((SOCKET_T)(s) < WOLFSSL_SOCKET_INVALID) + #endif +#endif /* WOLFSSL_SOCKET_INVALID */ + + +#ifdef SAMPLE_IPV6 + typedef struct sockaddr_in6 SOCKADDR_IN_T; + #define AF_INET_V AF_INET6 + static const char* const wolfSSLIP = "::1"; +#else + typedef struct sockaddr_in SOCKADDR_IN_T; + #define AF_INET_V AF_INET + static const char* const wolfSSLIP = "127.0.0.1"; +#endif +static const word16 wolfSSLPort = 11111; + +/* HPUX doesn't use socklent_t for third parameter to accept, unless + _XOPEN_SOURCE_EXTENDED is defined */ +#if (!defined(__hpux__) && !defined(WOLFSSL_MDK_ARM) && \ + !defined(WOLFSSL_IAR_ARM) && !defined(WOLFSSL_ROWLEY_ARM) && \ + !defined(WOLFSSL_KEIL_TCP_NET)) || defined(_XOPEN_SOURCE_EXTENDED) + typedef socklen_t* ACCEPT_THIRD_T; +#else + typedef int* ACCEPT_THIRD_T; +#endif + + +#ifdef USE_WINDOWS_API +static WC_INLINE int tcp_set_nonblocking(SOCKET_T* sockfd) +{ + int ret = 0; + unsigned long blocking = 1; + + ret = ioctlsocket(*sockfd, FIONBIO, &blocking); + if (ret == SOCKET_ERROR) + printf("ioctlsocket failed"); + + return ret; +} +#elif defined(WOLFSSL_MDK_ARM) || defined(WOLFSSL_KEIL_TCP_NET) || \ + defined(WOLFSSL_TIRTOS)|| defined(WOLFSSL_VXWORKS) || \ + defined(WOLFSSL_ZEPHYR) +static WC_INLINE int tcp_set_nonblocking(SOCKET_T* sockfd) +{ + (void)sockfd; + return 0; +} +#else +static WC_INLINE int tcp_set_nonblocking(SOCKET_T* sockfd) +{ + int ret = 0; + + int flags = fcntl(*sockfd, F_GETFL, 0); + if (flags < 0) { + printf("fcntl get failed"); + ret = -1; + } + flags = fcntl(*sockfd, F_SETFL, flags | O_NONBLOCK); + if (flags < 0) { + printf("fcntl set failed"); + ret = -1; + } + + return ret; +} +#endif + + +#if defined(HAVE_GETADDRINFO) || defined(WOLF_C99) + +#ifndef SAMPLE_IPV6 + +static WC_INLINE int get_addr(SOCKADDR_IN_T* addr, const char* peer, + word16 port, int udp, int sctp) +{ + int ret = 0; + struct addrinfo hints; + struct addrinfo* answer = NULL; + char strPort[6]; + + (void)sctp; + + XMEMSET(&hints, 0, sizeof(hints)); + + hints.ai_family = AF_INET_V; + if (udp) { + hints.ai_socktype = SOCK_DGRAM; + hints.ai_protocol = IPPROTO_UDP; + } +#ifdef WOLFSSL_SCTP + else if (sctp) { + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_SCTP; + } +#endif + else { + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + } + + SNPRINTF(strPort, sizeof(strPort), "%d", port); + strPort[sizeof(strPort)-1] = '\0'; + + ret = getaddrinfo(peer, strPort, &hints, &answer); + if (ret < 0 || answer == NULL) { + printf("getaddrinfo failed\n"); + ret = -1; + } + else + XMEMCPY(addr, answer->ai_addr, answer->ai_addrlen); + freeaddrinfo(answer); + + return ret; +} + +#else /* SAMPLE_IPV6 */ + +static WC_INLINE int get_addr(SOCKADDR_IN_T* addr, const char* peer, + word16 port, int udp, int sctp) +{ + int ret = 0; + struct zsock_addrinfo hints, *addrInfo; + char portStr[6]; + + (void)sctp; + + XSNPRINTF(portStr, sizeof(portStr), "%d", port); + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = udp ? SOCK_DGRAM : SOCK_STREAM; + hints.ai_protocol = udp ? IPPROTO_UDP : IPPROTO_TCP; + ret = getaddrinfo((char*)peer, portStr, &hints, &addrInfo); + if (ret == 0) + XMEMCPY(addr, addrInfo->ai_addr, sizeof(*addr)); + + return ret; +} + +#endif /* SAMPLE_IPV6 */ + +#else /* !GETADDRINFO */ + +#ifndef SAMPLE_IPV6 + +static WC_INLINE int get_addr(SOCKADDR_IN_T* addr, const char* peer, + word16 port, int udp, int sctp) +{ + int ret = 0; + #if defined(WOLFSSL_MDK_ARM) || defined(WOLFSSL_KEIL_TCP_NET) + int err; + struct hostent* entry = gethostbyname(peer, &err); + #elif defined(WOLFSSL_TIRTOS) + struct hostent* entry = DNSGetHostByName(peer); + #elif defined(WOLFSSL_VXWORKS) + struct hostent* entry = (struct hostent*)hostGetByName( + (char*)peer); + #else + struct hostent* entry = gethostbyname(peer); + #endif + + (void)port; + (void)udp; + (void)sctp; + + if (entry) + XMEMCPY(&addr->sin_addr.s_addr, entry->h_addr_list[0], entry->h_length); + else + ret = -1; + + return ret; +} + +#else + +static WC_INLINE int get_addr(SOCKADDR_IN_T* addr, const char* peer, + word16 port, int udp, int sctp) +{ + (void)peer; + (void)port; + (void)udp; + (void)sctp; + + printf("no ipv6 getaddrinfo, loopback only\n"); + addr->sin6_addr = in6addr_loopback; + + return 0; +} + +#endif /* SAMPLE_IPV6 */ + +#endif /* !GETADDRINFO */ + + + +static WC_INLINE int build_addr(SOCKADDR_IN_T* addr, const char* peer, + word16 port, int udp, int sctp) +{ + int ret = 0; + int useLookup = 0; + (void)useLookup; + + if (addr == NULL) { + printf("invalid argument to build_addr, addr is NULL\n"); + ret = -1; + } + + if (ret == 0) { + XMEMSET(addr, 0, sizeof(SOCKADDR_IN_T)); + +#ifndef SAMPLE_IPV6 + #if defined(WOLFSSL_MDK_ARM) || defined(WOLFSSL_KEIL_TCP_NET) + addr->sin_family = PF_INET; + #else + addr->sin_family = AF_INET_V; + #endif + addr->sin_port = XHTONS(port); + if ((size_t)peer == INADDR_ANY) + addr->sin_addr.s_addr = INADDR_ANY; + else { + /* peer could be in human readable form */ + if (isalpha((int)peer[0])) { + ret = get_addr(addr, peer, port, udp, sctp); + if (ret == 0) + useLookup = 1; + else + printf("no entry for host"); + } + if (ret == 0 && !useLookup) + addr->sin_addr.s_addr = inet_addr(peer); + } +#else /* SAMPLE_IPV6 */ + addr->sin6_family = AF_INET_V; + addr->sin6_port = XHTONS(port); + if ((size_t)peer == INADDR_ANY) + addr->sin6_addr = in6addr_any; + else + ret = get_addr(addr, peer, port, udp, sctp); +#endif /* SAMPL_IPV6 */ + } + + return ret; +} + + +#ifdef SO_NOSIGPIPE +static WC_INLINE int tcp_set_socket_no_sig_pipe(SOCKET_T sockfd) +{ + int ret; + int on = 1; + socklen_t len = sizeof(on); + + ret = setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, &on, len); + if (ret < 0) + printf("setsockopt SO_NOSIGPIPE failed\n"); + + return ret; +} +#elif defined(WOLFSSL_MDK_ARM) || defined (WOLFSSL_TIRTOS) || \ + defined(WOLFSSL_KEIL_TCP_NET) || defined(WOLFSSL_ZEPHYR) || \ + defined(USE_WINDOWS_API) +static WC_INLINE int tcp_set_socket_no_sig_pipe(SOCKET_T sockfd) +{ + (void)sockfd; + return 0; +} +#else +static WC_INLINE int tcp_set_socket_no_sig_pipe(SOCKET_T sockfd) +{ + signal(SIGPIPE, SIG_IGN); + return 0; +} +#endif + +#ifdef TCP_NODELAY +static WC_INLINE int tcp_set_socket_tcp_no_delay(SOCKET_T sockfd) +{ + int ret; + int on = 1; + socklen_t len = sizeof(on); + + ret = setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &on, len); + if (ret < 0) + printf("setsockopt TCP_NODELAY failed\n"); + + return ret; +} +#else +static WC_INLINE int tcp_set_socket_tcp_no_delay(SOCKET_T sockfd) +{ + return 0; +} +#endif + +static WC_INLINE int tcp_set_socket_opts(SOCKET_T sockfd, int udp, int sctp) +{ + int ret = 0; + + ret = tcp_set_socket_no_sig_pipe(sockfd); + if (ret == 0 && !udp && !sctp) + ret = tcp_set_socket_tcp_no_delay(sockfd); + + return ret; +} + +static WC_INLINE int tcp_socket(SOCKET_T* sockfd, int udp, int sctp) +{ + int ret = 0; + + if (udp) + *sockfd = socket(AF_INET_V, SOCK_DGRAM, IPPROTO_UDP); +#ifdef WOLFSSL_SCTP + else if (sctp) + *sockfd = socket(AF_INET_V, SOCK_STREAM, IPPROTO_SCTP); +#endif + else + *sockfd = socket(AF_INET_V, SOCK_STREAM, IPPROTO_TCP); + + if(WOLFSSL_SOCKET_IS_INVALID(*sockfd)) { + printf("socket failed\n"); + ret = -1; + } + + if (ret == 0) + ret = tcp_set_socket_opts(*sockfd, udp, sctp); + + return ret; +} + +static WC_INLINE int tcp_connect(SOCKET_T* sockfd, const char* ip, word16 port, + int udp, int sctp, WOLFSSL* ssl) +{ + int ret = 0; + SOCKADDR_IN_T addr; + + ret = build_addr(&addr, ip, port, udp, sctp); + if (ret != 0) + printf("build address failed\n"); + if (ret == 0) { + if (udp) + wolfSSL_dtls_set_peer(ssl, &addr, sizeof(addr)); + ret = tcp_socket(sockfd, udp, sctp); + } + + if (ret == 0 && !udp) { + if (connect(*sockfd, (const struct sockaddr*)&addr, sizeof(addr)) != + 0) { + printf("tcp connect failed"); + ret = -1; + } + } + + return ret; +} + + +#if defined(USE_WINDOWS_API) || defined(WOLFSSL_MDK_ARM) || \ + defined(WOLFSSL_KEIL_TCP_NET) || defined(WOLFSSL_ZEPHYR) +static WC_INLINE int tcp_set_socket_reuseaddr(SOCKET_T sockfd) +{ + (void)sockfd; + + return 0; +} +#else +static WC_INLINE int tcp_set_socket_reuseaddr(SOCKET_T sockfd) +{ + int ret; + int on = 1; + socklen_t len = sizeof(on); + + ret = setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, len); + if (ret < 0) + printf("setsockopt SO_REUSEADDR failed\n"); + + return ret; +} +#endif + +#if defined(USE_WINDOWS_API) || defined(WOLFSSL_TIRTOS) || \ + defined(WOLFSSL_ZEPHYR) +static WC_INLINE int tcp_get_sock_name(SOCKET_T sockfd, SOCKADDR_IN_T* addr, + word16* port) +{ + (void)sockfd; + (void)addr; + (void)port; + + return 0; +} +#else +static WC_INLINE int tcp_get_sock_name(SOCKET_T sockfd, SOCKADDR_IN_T* addr, + word16* port) +{ + socklen_t len = sizeof(*addr); + + if (getsockname(sockfd, (struct sockaddr*)addr, &len) == 0) { + #ifndef SAMPLE_IPV6 + *port = XNTOHS(addr->sin_port); + #else + *port = XNTOHS(addr->sin6_port); + #endif + } + + return 0; +} +#endif + +static WC_INLINE int tcp_listen(SOCKET_T* sockfd, word16* port, int useAnyAddr, + int udp, int sctp) +{ + int ret; + SOCKADDR_IN_T addr; + + /* don't use INADDR_ANY by default, firewall may block, make user switch + on */ + ret = build_addr(&addr, (useAnyAddr ? INADDR_ANY : wolfSSLIP), *port, udp, + sctp); + if (ret != 0) + printf("build address failed\n"); + if (ret == 0) { + ret = tcp_socket(sockfd, udp, sctp); + if (ret != 0) + printf("socket listen failed\n"); + } + + if (ret == 0) + ret = tcp_set_socket_reuseaddr(*sockfd); + + if (ret == 0) { + if (bind(*sockfd, (const struct sockaddr*)&addr, sizeof(addr)) != 0) { + printf("tcp bind failed\n"); + ret = -1; + } + } + if (ret == 0 && !udp) { + if (listen(*sockfd, SOCK_LISTEN_MAX_QUEUE) != 0) { + printf("tcp listen failed\n"); + ret = -1; + } + } + if (ret == 0 && *port == 0) + ret = tcp_get_sock_name(*sockfd, &addr, port); + + return ret; +} + +static WC_INLINE int tcp_accept(SOCKET_T* sockfd, SOCKET_T* clientfd) +{ + int ret = 0; + SOCKADDR_IN_T client; + socklen_t client_len = sizeof(client); + + *clientfd = accept(*sockfd, (struct sockaddr*)&client, + (ACCEPT_THIRD_T)&client_len); + if (WOLFSSL_SOCKET_IS_INVALID(*clientfd)) { + printf("tcp accept failed\n"); + ret = -1; + } + + return ret; +} + + diff --git a/embedded/threading.h b/embedded/threading.h new file mode 100644 index 00000000..490f5367 --- /dev/null +++ b/embedded/threading.h @@ -0,0 +1,62 @@ +/* threading.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 + */ + +#ifndef SINGLE_THREADED + +#if defined(_POSIX_THREADS) && !defined(__MINGW32__) + typedef void* THREAD_RETURN; + typedef pthread_t THREAD_TYPE; + #define WOLFSSL_THREAD + #define INFINITE -1 + #define WAIT_OBJECT_0 0L +#elif defined(WOLFSSL_MDK_ARM)|| defined(WOLFSSL_KEIL_TCP_NET) + typedef unsigned int THREAD_RETURN; + typedef int THREAD_TYPE; + #define WOLFSSL_THREAD +#elif defined(WOLFSSL_TIRTOS) + typedef void THREAD_RETURN; + typedef Task_Handle THREAD_TYPE; + #define WOLFSSL_THREAD +#elif defined(WOLFSSL_ZEPHYR) + typedef void THREAD_RETURN; + typedef struct k_thread THREAD_TYPE; + #define WOLFSSL_THREAD +#elif defined(USE_WINDOWS_API) + typedef unsigned int THREAD_RETURN; + typedef intptr_t THREAD_TYPE; + #define WOLFSSL_THREAD __stdcall +#else + #error "Threading API not supported in sample" +#endif + +typedef THREAD_RETURN WOLFSSL_THREAD THREAD_FUNC(void*); +typedef struct func_args { + int argc; + char** argv; + int return_code; +} func_args; + + +static void start_thread(THREAD_FUNC, func_args*, THREAD_TYPE*); +static void join_thread(THREAD_TYPE); + +#endif + diff --git a/embedded/tls-client-server.c b/embedded/tls-client-server.c new file mode 100644 index 00000000..e95de85d --- /dev/null +++ b/embedded/tls-client-server.c @@ -0,0 +1,480 @@ +/* tls-client-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 + */ + +#include +#include + +#include "certs.h" + + +/* I/O buffer size - wolfSSL buffers messages internally as well. */ +#define BUFFER_SIZE 2048 +/* Size of static buffer for dynamic memory allocation. */ +#ifdef WOLFSSL_STATIC_MEMORY_SMALL + #define STATIC_MEM_SIZE (24*1024) +#elif defined(HAVE_ECC) + #define STATIC_MEM_SIZE (144*1024) +#else + #define STATIC_MEM_SIZE (96*1024) +#endif + + +#ifdef WOLFSSL_STATIC_MEMORY + /* Hint pointers for dynamic memory allocating from buffer. */ + static WOLFSSL_HEAP_HINT* HEAP_HINT_SERVER; + static WOLFSSL_HEAP_HINT* HEAP_HINT_CLIENT; + + /* Static buffers to dynamically allocate from. */ + static byte gTestMemoryServer[STATIC_MEM_SIZE]; + static byte gTestMemoryClient[STATIC_MEM_SIZE]; +#else + #define HEAP_HINT_SERVER NULL + #define HEAP_HINT_CLIENT NULL +#endif /* WOLFSSL_STATIC_MEMORY */ + + +/* Buffer for client connection to allocate dynamic memory from. */ +static unsigned char client_buffer[BUFFER_SIZE]; +static int client_buffer_sz = 0; +/* Buffer for server connection to allocate dynamic memory from. */ +static unsigned char server_buffer[BUFFER_SIZE]; +static int server_buffer_sz = 0; + + +/* Application data to send. */ +static const char msgHTTPGet[] = "GET /index.html HTTP/1.0\r\n\r\n"; +static const char msgHTTPIndex[] = + "HTTP/1.1 200 OK\n" + "Content-Type: text/html\n" + "Connection: close\n" + "\n" + "\n" + "\n" + "Welcome to wolfSSL!\n" + "\n" + "\n" + "

wolfSSL 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 certiifcate\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 certiifcate\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..27acb8fa --- /dev/null +++ b/embedded/tls-sock-client-ca.c @@ -0,0 +1,261 @@ +/* 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 + */ + +#include +#include + +#include "sockets.h" +#include "tls-info.h" +#include "certs.h" + +/* Application data to send. */ +static const char msgHTTPGet[] = "GET /index.html HTTP/1.0\r\n\r\n"; + +/* Create a new wolfSSL client context with a server CA certificate and a + * client certificate and key. + */ +static int wolfssl_client_ctx_new(WOLFSSL_CTX** ctx) +{ + int ret = 0; + WOLFSSL_CTX* client_ctx = 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 certiifcate\n"); + ret = -1; + } + } + + if (ret == 0) { + /* Load client certificates into WOLFSSL_CTX */ + if (wolfSSL_CTX_use_certificate_buffer(client_ctx, CLIENT_CERT, + CLIENT_CERT_LEN, WOLFSSL_FILETYPE_ASN1) != WOLFSSL_SUCCESS) { + printf("ERROR: failed to load client certiifcate\n"); + ret = -1; + } + } + + if (ret == 0) { + /* Load client certificates into WOLFSSL_CTX */ + if (wolfSSL_CTX_use_PrivateKey_buffer(client_ctx, CLIENT_KEY, + CLIENT_KEY_LEN, WOLFSSL_FILETYPE_ASN1) != WOLFSSL_SUCCESS) { + printf("ERROR: failed to load client key\n"); + ret = -1; + } + } + + if (ret == 0) { + /* Return newly created wolfSSL context */ + *ctx = client_ctx; + } + else { + if (client_ctx != NULL) + wolfSSL_CTX_free(client_ctx); + } + + return ret; +} + +/* Create a new wolfSSL client object. */ +static int wolfssl_client_ssl_new(WOLFSSL_CTX* ctx, WOLFSSL** ssl) +{ + int ret = 0; + WOLFSSL* client_ssl = NULL; + + /* Create a WOLFSSL object */ + if ((client_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(client_ssl, 1); + } + + if (ret == 0) { + /* Return newly created wolfSSL object */ + *ssl = client_ssl; + } + else { + if (client_ssl != NULL) + wolfSSL_free(client_ssl); + } + + 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; +} + + +/* 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; +} + + +/* 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) { + if (wolfSSL_set_fd(ssl, *fd) != WOLFSSL_SUCCESS) + ret = -1; + } + + return ret; +} + +/* Client connection operations */ +static int client(WOLFSSL_CTX* client_ctx) +{ + int ret = 0; + WOLFSSL* client_ssl = NULL; + SOCKET_T sockfd = WOLFSSL_SOCKET_INVALID; + + /* Create a new client connection */ + ret = wolfssl_client_ssl_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) + showPeerEx(client_ssl, 0); + + /* Send HTTP request */ + if (ret == 0) + ret = wolfssl_send(client_ssl, msgHTTPGet); + /* Receive HTTP response */ + if (ret == 0) + ret = wolfssl_recv(client_ssl); + + if (sockfd != WOLFSSL_SOCKET_INVALID) + CloseSocket(sockfd); + if (client_ssl != NULL) + wolfSSL_free(client_ssl); + + return ret; +} + +int main(int argc, char* argv[]) +{ + int ret = 0; + WOLFSSL_CTX* client_ctx = NULL; + +#if defined(DEBUG_WOLFSSL) + wolfSSL_Debugging_ON(); +#endif + /* Initialise wolfSSL library */ + wolfSSL_Init(); + + ret = wolfssl_client_ctx_new(&client_ctx); + + /* Do client */ + client(client_ctx); + + if (client_ctx != NULL) + wolfSSL_CTX_free(client_ctx); + + /* 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-client.c b/embedded/tls-sock-client.c new file mode 100644 index 00000000..5a28fbf0 --- /dev/null +++ b/embedded/tls-sock-client.c @@ -0,0 +1,241 @@ +/* tls-sock-client.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 + */ + +#include +#include + +#include "sockets.h" +#include "tls-info.h" +#include "certs.h" + +/* Application data to send. */ +static const char msgHTTPGet[] = "GET /index.html HTTP/1.0\r\n\r\n"; + +/* Create a new wolfSSL client context with a server CA certificate. */ +static int wolfssl_client_ctx_new(WOLFSSL_CTX** ctx) +{ + int ret = 0; + WOLFSSL_CTX* client_ctx = 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 certiifcate\n"); + ret = -1; + } + } + + if (ret == 0) { + /* Return newly created wolfSSL context */ + *ctx = client_ctx; + } + else { + if (client_ctx != NULL) + wolfSSL_CTX_free(client_ctx); + } + + return ret; +} + +/* Create a new wolfSSL client object. */ +static int wolfssl_client_ssl_new(WOLFSSL_CTX* ctx, WOLFSSL** ssl) +{ + int ret = 0; + WOLFSSL* client_ssl = NULL; + + /* Create a WOLFSSL object */ + if ((client_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(client_ssl, 1); + } + + if (ret == 0) { + /* Return newly created wolfSSL object */ + *ssl = client_ssl; + } + else { + if (client_ssl != NULL) + wolfSSL_free(client_ssl); + } + + 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; +} + + +/* 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; +} + + +/* 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) { + if (wolfSSL_set_fd(ssl, *fd) != WOLFSSL_SUCCESS) + ret = -1; + } + + return ret; +} + +/* Client connection operations */ +static int client(WOLFSSL_CTX* client_ctx) +{ + int ret = 0; + WOLFSSL* client_ssl = NULL; + SOCKET_T sockfd = WOLFSSL_SOCKET_INVALID; + + /* Create a new client connection */ + ret = wolfssl_client_ssl_new(client_ctx, &client_ssl); + + if (ret == 0) + ret = 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) + showPeerEx(client_ssl, 0); + + /* Send HTTP request */ + if (ret == 0) + ret = wolfssl_send(client_ssl, msgHTTPGet); + /* Receive HTTP response */ + if (ret == 0) + ret = wolfssl_recv(client_ssl); + + if (sockfd != WOLFSSL_SOCKET_INVALID) + CloseSocket(sockfd); + if (client_ssl != NULL) + wolfSSL_free(client_ssl); + + return ret; +} + +int main(int argc, char* argv[]) +{ + int ret = 0; + WOLFSSL_CTX* client_ctx = NULL; + +#if defined(DEBUG_WOLFSSL) + wolfSSL_Debugging_ON(); +#endif + /* Initialise wolfSSL library */ + wolfSSL_Init(); + + ret = wolfssl_client_ctx_new(&client_ctx); + + /* Do client */ + ret = client(client_ctx); + + if (client_ctx != NULL) + wolfSSL_CTX_free(client_ctx); + + /* 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-ca.c b/embedded/tls-sock-server-ca.c new file mode 100644 index 00000000..dfa3babc --- /dev/null +++ b/embedded/tls-sock-server-ca.c @@ -0,0 +1,298 @@ +/* tls-sock-server-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 + */ + +#include +#include + +#include "sockets.h" +#include "tls-info.h" +#include "certs.h" + +/* Application data to send. */ +static const char msgHTTPIndex[] = + "HTTP/1.1 200 OK\n" + "Content-Type: text/html\n" + "Connection: close\n" + "\n" + "\n" + "\n" + "Welcome to wolfSSL!\n" + "\n" + "\n" + "

wolfSSL 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 certiifcate\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 certiifcate\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 repsonse */ + 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..62634a31 --- /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 + */ + +#include +#include + +#include "sockets.h" +#include "tls-info.h" +#include "certs.h" + +/* Application data to send. */ +static const char msgHTTPIndex[] = + "HTTP/1.1 200 OK\n" + "Content-Type: text/html\n" + "Connection: close\n" + "\n" + "\n" + "\n" + "Welcome to wolfSSL!\n" + "\n" + "\n" + "

wolfSSL 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 certiifcate\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 repsonse */ + 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..c89a2998 --- /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 + */ + +#include +#include + +#ifndef SINGLE_THREADED + +#include "sockets.h" +#include "threading.h" +#include "certs.h" + +/* Mutex to wait for server to be ready. */ +wolfSSL_Mutex server_mutex; + +/* Application data to send. */ +static const char msgHTTPGet[] = "GET /index.html HTTP/1.0\r\n\r\n"; +static const char msgHTTPIndex[] = + "HTTP/1.1 200 OK\n" + "Content-Type: text/html\n" + "Connection: close\n" + "\n" + "\n" + "\n" + "Welcome to wolfSSL!\n" + "\n" + "\n" + "

wolfSSL 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 certiifcate\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 certiifcate\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 repsonse */ + 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 conenction 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..2cb6d32a --- /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 + */ + +#include +#include + +#ifndef SINGLE_THREADED + +#include "threading.h" +#include "certs.h" + + +/* I/O buffer size - wolfSSL buffers messages internally as well. */ +#define BUFFER_SIZE 2048 + + +/* Buffer to hold data for client to read. */ +unsigned char client_buffer[BUFFER_SIZE]; +int client_buffer_sz = 0; +/* Mutex protecting access to client's read buffer. */ +wolfSSL_Mutex client_mutex; + +/* Buffer to hold data for server to read. */ +unsigned char server_buffer[BUFFER_SIZE]; +int server_buffer_sz = 0; +/* Mutex protecting access to server's read buffer. */ +wolfSSL_Mutex server_mutex; + +/* Application data to send. */ +static const char msgHTTPGet[] = "GET /index.html HTTP/1.0\r\n\r\n"; +static const char msgHTTPIndex[] = + "HTTP/1.1 200 OK\n" + "Content-Type: text/html\n" + "Connection: close\n" + "\n" + "\n" + "\n" + "Welcome to wolfSSL!\n" + "\n" + "\n" + "

wolfSSL 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 certiifcate\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 certiifcate\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 repsonse */ + 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 conenction 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