diff --git a/tls/Makefile b/tls/Makefile index 1367c53c..31050383 100644 --- a/tls/Makefile +++ b/tls/Makefile @@ -2,7 +2,7 @@ CC=gcc CFLAGS=-Wall LIBS=-lwolfssl -all: client-tcp client-tls client-tls-nonblocking client-tls-resume client-callback server-tcp server-tls server-tls-nonblocking server-tls-threaded server-callback +all: client-tcp client-tls client-tls-nonblocking client-tls-ecdhe server-tls-ecdhe client-tls-resume client-callback server-tcp server-tls server-tls-nonblocking server-tls-threaded server-callback client-tcp: client-tcp.o $(CC) -o $@ $^ $(CFLAGS) @@ -13,6 +13,12 @@ client-tls: client-tls.o client-tls-nonblocking: client-tls-nonblocking.o $(CC) -o $@ $^ $(CFLAGS) $(LIBS) +client-tls-ecdhe: client-tls-ecdhe.o + $(CC) -o $@ $^ $(CFLAGS) $(LIBS) + +server-tls-ecdhe: server-tls-ecdhe.o + $(CC) -o $@ $^ $(CFLAGS) $(LIBS) + client-tls-resume: client-tls-resume.o $(CC) -o $@ $^ $(CFLAGS) $(LIBS) @@ -37,4 +43,4 @@ server-callback: server-callback.o .PHONY: clean all clean: - rm -f *.o client-tcp client-tls client-tls-nonblocking client-tls-resume client-callback server-tcp server-tls server-tls-nonblocking server-tls-threaded server-callback + rm -f *.o client-tcp client-tls client-tls-nonblocking client-tls-ecdhe server-tls-ecdhe client-tls-resume client-callback server-tcp server-tls server-tls-nonblocking server-tls-threaded server-callback diff --git a/tls/client-tls-ecdhe.c b/tls/client-tls-ecdhe.c new file mode 100644 index 00000000..52768ce7 --- /dev/null +++ b/tls/client-tls-ecdhe.c @@ -0,0 +1,174 @@ +/* client-tls.c + * + * Copyright (C) 2006-2015 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 +#include +#include +#include +#include /* wolfSSL security library */ +#include + +#define MAXDATASIZE 4096 /* maximum acceptable amount of data */ +#define SERV_PORT 11111 /* define default port number */ + +const char* cert = "../certs/server-ecc.pem"; + +/* + * clients initial contact with server. (socket to connect, security layer) + */ +int ClientGreet(int sock, WOLFSSL* ssl) +{ + /* data to send to the server, data recieved from the server */ + char sendBuff[MAXDATASIZE], rcvBuff[MAXDATASIZE] = {0}; + int ret = 0; /* variable for error checking */ + + printf("Message for server:\t"); + fgets(sendBuff, MAXDATASIZE, stdin); + + if (wolfSSL_write(ssl, sendBuff, strlen(sendBuff)) != strlen(sendBuff)) { + /* the message is not able to send, or error trying */ + ret = wolfSSL_get_error(ssl, 0); + printf("Write error: Error: %i\n", ret); + return EXIT_FAILURE; + } + + if (wolfSSL_read(ssl, rcvBuff, MAXDATASIZE) < 0) { + /* the server failed to send data, or error trying */ + ret = wolfSSL_get_error(ssl, 0); + printf("Read error. Error: %i\n", ret); + return EXIT_FAILURE; + } + printf("Recieved: \t%s\n", rcvBuff); + + return ret; +} + +/* + * applies TLS 1.2 security layer to data being sent. + */ +int Security(int sock) +{ + WOLFSSL_CTX* ctx; + WOLFSSL* ssl; /* create WOLFSSL object */ + int ret = 0; + const char* myCert = "../certs/client-ecc-cert.pem"; + const char* myKey = "../certs/ecc-client-key.pem"; + char* cipherList = "ECDHE-ECDSA-CHACHA20-POLY1305"; + char buffer[WOLFSSL_MAX_ERROR_SZ]; + + wolfSSL_Init(); /* initialize wolfSSL */ + + /* create and initiLize WOLFSSL_CTX structure */ + if ((ctx = wolfSSL_CTX_new(wolfTLSv1_2_client_method())) == NULL) { + printf("SSL_CTX_new error.\n"); + return EXIT_FAILURE; + } + + if (wolfSSL_CTX_set_cipher_list(ctx, cipherList) != SSL_SUCCESS) + err_sys("client can't set cipher list 1"); + + if (wolfSSL_CTX_use_certificate_chain_file(ctx, myCert) + != SSL_SUCCESS) + err_sys("can't load client cert file, check file and run from" + " wolfSSL home dir"); + + if (wolfSSL_CTX_use_PrivateKey_file(ctx, myKey, SSL_FILETYPE_PEM) + != SSL_SUCCESS) + err_sys("can't load client private key file, check file and run " + "from wolfSSL home dir"); + + /* load CA certificates into wolfSSL_CTX. which will verify the server */ + if (wolfSSL_CTX_load_verify_locations(ctx, cert, 0) != SSL_SUCCESS) { + printf("Error loading %s. Please check the file.\n", cert); + return EXIT_FAILURE; + } + + if ((ssl = wolfSSL_new(ctx)) == NULL) { + printf("wolfSSL_new error.\n"); + return EXIT_FAILURE; + } + wolfSSL_set_fd(ssl, sock); + + ret = wolfSSL_connect(ssl); + if (ret == SSL_SUCCESS) { + ret = ClientGreet(sock, ssl); + } else { + printf("Failure:"); + ret = wolfSSL_get_error(ssl, 0); + printf(" ret = %d", ret); + printf(" %s\n", wolfSSL_ERR_error_string(ret, buffer)); + } + + + /* frees all data before client termination */ + wolfSSL_free(ssl); + wolfSSL_CTX_free(ctx); + wolfSSL_Cleanup(); + + return ret; +} + +/* + * Command line argumentCount and argumentValues + */ +int main(int argc, char** argv) +{ + int sockfd; /* socket file descriptor */ + struct sockaddr_in servAddr; /* struct for server address */ + int ret = 0; /* variable for error checking */ + + if (argc != 2) { + /* if the number of arguments is not two, error */ + printf("usage: ./client-tcp \n"); + return EXIT_FAILURE; + } + + /* internet address family, stream based tcp, default protocol */ + sockfd = socket(AF_INET, SOCK_STREAM, 0); + + if (sockfd < 0) { + printf("Failed to create socket. Error: %i\n", errno); + return EXIT_FAILURE; + } + + memset(&servAddr, 0, sizeof(servAddr)); /* clears memory block for use */ + servAddr.sin_family = AF_INET; /* sets addressfamily to internet*/ + servAddr.sin_port = htons(SERV_PORT); /* sets port to defined port */ + + /* looks for the server at the entered address (ip in the command line) */ + if (inet_pton(AF_INET, argv[1], &servAddr.sin_addr) < 1) { + /* checks validity of address */ + ret = errno; + printf("Invalid Address. Error: %i\n", ret); + return EXIT_FAILURE; + } + + if (connect(sockfd, (struct sockaddr *) &servAddr, sizeof(servAddr)) < 0) { + /* if socket fails to connect to the server*/ + ret = errno; + printf("Connect error. Error: %i\n", ret); + return EXIT_FAILURE; + } + Security(sockfd); + + return ret; +} diff --git a/tls/server-tls-ecdhe.c b/tls/server-tls-ecdhe.c new file mode 100644 index 00000000..7ac3eeb0 --- /dev/null +++ b/tls/server-tls-ecdhe.c @@ -0,0 +1,195 @@ +/* server-tls.c + * + * Copyright (C) 2006-2015 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 + *============================================================================= + * + * This is a super basic example of what a TCP Server secured with TLS 1.2 + * might look like. This server can also resume the session if a client + * inadvertantly disconnects. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* include the wolfSSL library for our TLS 1.2 security */ +#include + +#define DEFAULT_PORT 11111 + +int AcceptAndRead(WOLFSSL_CTX* ctx, socklen_t sockfd, struct sockaddr_in + clientAddr); + +int AcceptAndRead(WOLFSSL_CTX* ctx, socklen_t sockfd, struct sockaddr_in + clientAddr) +{ + /* Create our reply message */ + const char reply[] = "I hear ya fa shizzle!\n"; + socklen_t size = sizeof(clientAddr); + + /* Wait until a client connects */ + socklen_t connd = accept(sockfd, (struct sockaddr *)&clientAddr, &size); + + /* If fails to connect,int loop back up and wait for a new connection */ + if (connd == -1) { + printf("failed to accept the connection..\n"); + } + /* If it connects, read in and reply to the client */ + else { + printf("Client connected successfully\n"); + WOLFSSL* ssl; + + if ( (ssl = wolfSSL_new(ctx)) == NULL) { + fprintf(stderr, "wolfSSL_new error.\n"); + exit(EXIT_FAILURE); + } + + /* direct our ssl to our clients connection */ + wolfSSL_set_fd(ssl, connd); + + printf("Using Non-Blocking I/O: %d\n", wolfSSL_get_using_nonblock( + ssl)); + + for ( ; ; ) { + char buff[256]; + int ret = 0; + + /* Clear the buffer memory for anything possibly left over */ + memset(&buff, 0, sizeof(buff)); + + /* Read the client data into our buff array */ + if ((ret = wolfSSL_read(ssl, buff, sizeof(buff)-1)) > 0) { + /* Print any data the client sends to the console */ + printf("Client: %s\n", buff); + + /* Reply back to the client */ + if ((ret = wolfSSL_write(ssl, reply, sizeof(reply)-1)) + < 0) + { + printf("wolfSSL_write error = %d\n", wolfSSL_get_error(ssl, ret)); + } + } + /* if the client disconnects break the loop */ + else { + if (ret < 0) + printf("wolfSSL_read error = %d\n", wolfSSL_get_error(ssl + ,ret)); + else if (ret == 0) + printf("The client has closed the connection.\n"); + + break; + } + } + wolfSSL_free(ssl); /* Free the WOLFSSL object */ + } + close(connd); /* close the connected socket */ + + return 0; +} + + +int main() +{ + /* Create a ctx pointer for our ssl */ + WOLFSSL_CTX* ctx; + + /* + * Creates a socket that uses an internet IP address, + * Sets the type to be Stream based (TCP), + * 0 means choose the default protocol. + */ + socklen_t sockfd = socket(AF_INET, SOCK_STREAM, 0); + int loopExit = 0; /* 0 = False, 1 = True */ + int ret = 0; /* Return value */ + /* Server and client socket address structures */ + struct sockaddr_in serverAddr, clientAddr; + char* cipherList = "ECDHE-ECDSA-CHACHA20-POLY1305"; + + /* Initialize wolfSSL */ + wolfSSL_Init(); + + /* If positive value, the socket is valid */ + if (sockfd == -1) { + printf("ERROR: failed to create the socket\n"); + return EXIT_FAILURE; /* Kill the server with exit status 1 */ + } + + /* create and initialize WOLFSSL_CTX structure */ + if ((ctx = wolfSSL_CTX_new(wolfTLSv1_2_server_method())) == NULL) { + fprintf(stderr, "wolfSSL_CTX_new error.\n"); + return EXIT_FAILURE; + } + + /* Load server certificate into WOLFSSL_CTX */ + if (wolfSSL_CTX_use_certificate_file(ctx, "../certs/server-ecc.pem", + SSL_FILETYPE_PEM) != SSL_SUCCESS) { + fprintf(stderr, "Error loading certs/server-cert.pem, please check" + "the file.\n"); + return EXIT_FAILURE; + } + + /* Load server key into WOLFSSL_CTX */ + if (wolfSSL_CTX_use_PrivateKey_file(ctx, "../certs/ecc-key.pem", + SSL_FILETYPE_PEM) != SSL_SUCCESS) { + fprintf(stderr, "Error loading certs/server-key.pem, please check" + "the file.\n"); + return EXIT_FAILURE; + } + + if (wolfSSL_CTX_set_cipher_list(ctx, cipherList) != SSL_SUCCESS) + printf("client can't set cipher list 1"); + + /* Initialize the server address struct to zero */ + memset((char *)&serverAddr, 0, sizeof(serverAddr)); + + /* Fill the server's address family */ + serverAddr.sin_family = AF_INET; + serverAddr.sin_addr.s_addr = INADDR_ANY; + serverAddr.sin_port = htons(DEFAULT_PORT); + + /* Attach the server socket to our port */ + if (bind(sockfd, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) + < 0) { + printf("ERROR: failed to bind\n"); + return EXIT_FAILURE; + } + + printf("Waiting for a connection...\n"); + /* Continuously accept connects while not currently in an active connection + or told to quit */ + while (loopExit == 0) { + /* listen for a new connection, allow 5 pending connections */ + ret = listen(sockfd, 5); + if (ret == 0) { + + /* Accept client connections and read from them */ + loopExit = AcceptAndRead(ctx, sockfd, clientAddr); + } + } + + wolfSSL_CTX_free(ctx); /* Free WOLFSSL_CTX */ + wolfSSL_Cleanup(); /* Free wolfSSL */ + return EXIT_SUCCESS; +}