From 208ef9b8991243e01060f0753d752cbb051279d0 Mon Sep 17 00:00:00 2001 From: kaleb-himes Date: Wed, 14 Dec 2016 17:07:25 -0700 Subject: [PATCH] custom io callback examples using the file system use already available certs --- .gitignore | 4 + custom-io-callbacks/README.md | 50 +++ custom-io-callbacks/file-client/Makefile | 16 + .../file-client/clean-io-files.sh | 7 + .../client_read_server_write_file.txt | 0 .../client_write_server_read_file.txt | 0 custom-io-callbacks/file-client/file-client.c | 296 ++++++++++++++++++ custom-io-callbacks/file-server/Makefile | 16 + custom-io-callbacks/file-server/check.sh | 17 + custom-io-callbacks/file-server/file-server.c | 276 ++++++++++++++++ 10 files changed, 682 insertions(+) create mode 100644 custom-io-callbacks/README.md create mode 100644 custom-io-callbacks/file-client/Makefile create mode 100755 custom-io-callbacks/file-client/clean-io-files.sh create mode 100644 custom-io-callbacks/file-client/client_read_server_write_file.txt create mode 100644 custom-io-callbacks/file-client/client_write_server_read_file.txt create mode 100644 custom-io-callbacks/file-client/file-client.c create mode 100644 custom-io-callbacks/file-server/Makefile create mode 100755 custom-io-callbacks/file-server/check.sh create mode 100644 custom-io-callbacks/file-server/file-server.c diff --git a/.gitignore b/.gitignore index e2b743a8..52da51c2 100644 --- a/.gitignore +++ b/.gitignore @@ -22,6 +22,7 @@ *.x86_64 *.hex + # Android files android/wolfssljni-ndk-sample/bin android/wolfssljni-ndk-sample/build.xml @@ -68,6 +69,9 @@ crypto/aes/aes-file-encrypt crypto/camellia/camellia-encrypt crypto/keys/ecc_keys +*/file-client/start-client +*/file-server/start-server + #Example der and x963 files crypto/keys/*.der crypto/keys/*.x963 diff --git a/custom-io-callbacks/README.md b/custom-io-callbacks/README.md new file mode 100644 index 00000000..d984971a --- /dev/null +++ b/custom-io-callbacks/README.md @@ -0,0 +1,50 @@ +This is an example to demonstrate how the custom IO callbacks can be used to +facilitate a TLS connection using any medium. Here we chose the medium of files. + +Other mediums might be: +USB Serial connection +Bluetooth +RFID +Wifi +Ethernet + +To name a few. + +These examples use the wolfSSL Custom IO Callbacks to read and write to the file +system and perform a successful handshake. + +The configuration used for these examples was: +./configure --enable-debug + +Debug was enabled in case a user wishes to use the verbose flag to see what is +happening in real time: + +Usage examples: + +From the file-server directory: +./start-server +./start-server -v +./start-server -verbose + +From the file-client directory: +./start-client +./start-client -v +./start-client -verbose + +(-v and -verbose accomplish the same thing) + + +SCRIPTS: The scripts provided attempt to make testing easier. + +file-server/check.sh + - starts the server in a background shell and runs the client +USAGE: + ./check.sh + ./check.sh -v + ./check.sh -verbose + +file-client/clean-io-files.sh + - If something happens and there is leftover junk in the io files run this + script to quickly cleanup before next round of testing. +USAGE: + ./clean-io-files.sh diff --git a/custom-io-callbacks/file-client/Makefile b/custom-io-callbacks/file-client/Makefile new file mode 100644 index 00000000..6a1f0b14 --- /dev/null +++ b/custom-io-callbacks/file-client/Makefile @@ -0,0 +1,16 @@ +CC=clang +# if you installed wolfssl to /usr/local please make sure the path to +# /usr/local/include is in your -I path and /usr/local/lib is in your +# LD_LIBRARY_PATH +CFLAGS=-Wall +LIBS= -L/usr/local/lib -lwolfssl + +all:start-client + +start-client:file-client.o + $(CC) -o $@ $(LIBS) $^ $(CFLAGS) + +.PHONY: clean all + +clean: + rm -f *.o file-client.o start-client diff --git a/custom-io-callbacks/file-client/clean-io-files.sh b/custom-io-callbacks/file-client/clean-io-files.sh new file mode 100755 index 00000000..c949a01a --- /dev/null +++ b/custom-io-callbacks/file-client/clean-io-files.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +rm client_read_server_write_file.txt +rm client_write_server_read_file.txt + +touch client_read_server_write_file.txt +touch client_write_server_read_file.txt diff --git a/custom-io-callbacks/file-client/client_read_server_write_file.txt b/custom-io-callbacks/file-client/client_read_server_write_file.txt new file mode 100644 index 00000000..e69de29b diff --git a/custom-io-callbacks/file-client/client_write_server_read_file.txt b/custom-io-callbacks/file-client/client_write_server_read_file.txt new file mode 100644 index 00000000..e69de29b diff --git a/custom-io-callbacks/file-client/file-client.c b/custom-io-callbacks/file-client/file-client.c new file mode 100644 index 00000000..7cb96147 --- /dev/null +++ b/custom-io-callbacks/file-client/file-client.c @@ -0,0 +1,296 @@ +/* file-client.c + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + * + * EXAMPLE DEFINIITON: + * + * Instead of using sockets we will show how it is possible + * to deliver TLS handshake and packet exchange through the use of + * the file system! We will accomplish this using the wolfSSL + * IO callbacks to read/write to files instead of using sockets + */ + +/*--------------------------------------------------------------*/ +/* Header files and definitions */ +/*--------------------------------------------------------------*/ +#include + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include +#include + +#define MAXSZ 1024 +/* use the certs already available in the examples repo */ +#define clientCert "../../certs/client-cert.pem" +#define peerAuthority "../../certs/server-cert.pem" +#define CR "client_read_server_write_file.txt" +#define SR "client_write_server_read_file.txt" + +/*--------------------------------------------------------------*/ +/* Function Prototypes and global variables */ +/*--------------------------------------------------------------*/ +unsigned int my_psk_client_cb(WOLFSSL* ssl, const char* hint, + char* identity, unsigned int id_max_len, + unsigned char* Xkey, unsigned int key_max_len); + +int CbIOSend(WOLFSSL *ssl, char *buf, int sz, void *ctx); +int CbIORecv(WOLFSSL *ssl, char *buf, int sz, void *ctx); +WOLFSSL* Client(WOLFSSL_CTX* ctx, char* suite, int setSuite, int doVerify); +WOLFSSL_METHOD* SetMethodClient(int i); + + +struct WOLFSSL_SOCKADDR { + unsigned int sz; + void* sa; +}; + +static int fpSend; +static int fpRecv; +static int verboseFlag = 0; + +/*--------------------------------------------------------------*/ +/* Function implementations */ +/*--------------------------------------------------------------*/ +//unsigned int my_psk_client_cb(WOLFSSL* ssl, const char* hint, +// char* identity, unsigned int id_max_len, unsigned char* Xkey, +// unsigned int key_max_len) +//{ +// (void)ssl; +// (void)hint; +// (void)key_max_len; +// +// /* identity is OpenSSL testing default for openssl s_client, keep same */ +// strncpy(identity, "Client_identity", id_max_len); +// +// +// /* test key in hex is 0x1a2b3c4d , in decimal 439,041,101 , we're using +// unsigned binary */ +// Xkey[0] = 26; +// Xkey[1] = 43; +// Xkey[2] = 60; +// Xkey[3] = 77; +// +// return 4; /* length of key in octets or 0 for error */ +//} + +int CbIORecv(WOLFSSL *ssl, char *buf, int sz, void *ctx) +{ + (void) ssl; /* will not need ssl context, just using the file system */ + (void) ctx; /* will not need ctx, we're just using the file system */ + int ret = 0; + int i; + + while (ret <= 0) + ret = (int) read(fpRecv, buf, (size_t) sz); + if (verboseFlag == 1) { + printf("/*-------------------- CLIENT READING -----------------*/\n"); + for (i = 0; i < ret; i++) { + printf("%02x ", (unsigned char)buf[i]); + if (i > 0 && (i % 16) == 0) + printf("\n"); + } + printf("\n/*-------------------- CLIENT READING -----------------*/\n"); + } + + return ret; +} + +int CbIOSend(WOLFSSL *ssl, char *buf, int sz, void *ctx) +{ + (void) ssl; /* will not need ssl context, just using the file system */ + (void) ctx; /* will not need ctx, we're just using the file system */ + int ret; + int i; + + ret = (int) write(fpSend, buf, (size_t) sz); + if (verboseFlag == 1) { + printf("/*-------------------- CLIENT SENDING -----------------*/\n"); + for (i = 0; i < sz; i++) { + printf("%02x ", (unsigned char) buf[i]); + if (i > 0 && (i % 16) == 0) + printf("\n"); + } + printf("\n/*-------------------- CLIENT SENDING -----------------*/\n"); + } else { + (void) i; + } + + return ret; +} + +WOLFSSL* Client(WOLFSSL_CTX* ctx, char* suite, int setSuite, int doVerify) +{ + WOLFSSL* ssl = NULL; + int ret; + + if ((ctx = wolfSSL_CTX_new(wolfTLSv1_2_client_method())) == NULL) { + printf("Error in setting client ctx\n"); + return NULL; + } + + if (doVerify == 1) { + if ((wolfSSL_CTX_load_verify_locations(ctx, peerAuthority, 0)) + != SSL_SUCCESS) { + printf("Failed to load CA (peer Authority) file\n"); + return NULL; + } + } else { + wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, 0); + } + + if (setSuite == 1) { + if ((ret = wolfSSL_CTX_set_cipher_list(ctx, suite)) != SSL_SUCCESS) { + printf("ret = %d\n", ret); + printf("can't set cipher\n"); + wolfSSL_CTX_free(ctx); + return NULL; + } + } else { + (void) suite; + } + + wolfSSL_SetIORecv(ctx, CbIORecv); + wolfSSL_SetIOSend(ctx, CbIOSend); + + if ((ssl = wolfSSL_new(ctx)) == NULL) { + printf("issue when creating ssl\n"); + wolfSSL_CTX_free(ctx); + return NULL; + } + + wolfSSL_set_fd(ssl, fpRecv); + wolfSSL_set_using_nonblock(ssl, fpRecv); + + return ssl; +} + + +int main(int argc, char** argv) +{ + char msg[] = "Hello wolfSSL\r\n"; + char reply[MAXSZ]; + int ret, msgSz; + WOLFSSL* sslCli; + WOLFSSL_CTX* ctxCli = NULL; + + if (argc == 2) { + if (XSTRNCMP(argv[1], "-verbose", 8) == 0 || + XSTRNCMP(argv[1], "-v", 2) == 0) { + verboseFlag = 1; + } + } + + fpSend = open(SR, O_WRONLY | O_NOCTTY | O_NDELAY); + fpRecv = open(CR, O_RDONLY | O_NOCTTY | O_NDELAY); + + wolfSSL_Init(); + + /* Example usage */ +// sslServ = Server(ctxServ, "ECDHE-RSA-AES128-SHA", 1); + sslCli = Client(ctxCli, "let-wolfssl-decide", 0, 1); + + if (sslCli == NULL) { + printf("Failed to start client\n"); + goto cleanup; + } + + ret = SSL_FAILURE; + + printf("Starting client\n"); + while (ret != SSL_SUCCESS) { + int error; + + /* client connect */ + ret |= wolfSSL_connect(sslCli); + error = wolfSSL_get_error(sslCli, 0); + if (ret != SSL_SUCCESS) { + if (error != SSL_ERROR_WANT_READ && + error != SSL_ERROR_WANT_WRITE) { + wolfSSL_free(sslCli); + wolfSSL_CTX_free(ctxCli); + printf("client ssl connect failed\n"); + goto cleanup; + } + } + printf("Client connected successfully...\n"); + } + + + /* read and write */ + while (1) { + int error; + + /* client send/read */ + msgSz = (int) strlen(msg); + ret = wolfSSL_write(sslCli, msg, msgSz); + error = wolfSSL_get_error(sslCli, 0); + if (ret != msgSz) { + if (error != SSL_ERROR_WANT_READ && + error != SSL_ERROR_WANT_WRITE) { + printf("client write failed\n"); + break; + } + } + + ret = wolfSSL_read(sslCli, reply, sizeof(reply) - 1); + error = wolfSSL_get_error(sslCli, 0); + if (ret < 0) { + if (error != SSL_ERROR_WANT_READ && + error != SSL_ERROR_WANT_WRITE) { + printf("client read failed\n"); + break; + } + } + else { + reply[ret] = '\0'; + printf("Client Received Reply: %s\n", reply); + break; + } + + } + +cleanup: + + wolfSSL_shutdown(sslCli); + wolfSSL_free(sslCli); + wolfSSL_CTX_free(ctxCli); + wolfSSL_Cleanup(); + /* close the streams so client can reset file contents */ + close(fpSend); + close(fpRecv); + close(open(CR, O_RDWR | O_NOCTTY | O_NDELAY)); + close(open(SR, O_RDWR | O_NOCTTY | O_NDELAY)); + + return -1; +} diff --git a/custom-io-callbacks/file-server/Makefile b/custom-io-callbacks/file-server/Makefile new file mode 100644 index 00000000..a1a27d4e --- /dev/null +++ b/custom-io-callbacks/file-server/Makefile @@ -0,0 +1,16 @@ +CC=clang +# if you installed wolfssl to /usr/local please make sure the path to +# /usr/local/include is in your -I path and /usr/local/lib is in your +# LD_LIBRARY_PATH +CFLAGS=-Wall +LIBS=-L/usr/local/lib -lwolfssl + +all:start-server + +start-server:file-server.o + $(CC) -o $@ $(LIBS) $^ $(CFLAGS) + +.PHONY: clean all + +clean: + rm -f *.o file-server.o start-server diff --git a/custom-io-callbacks/file-server/check.sh b/custom-io-callbacks/file-server/check.sh new file mode 100755 index 00000000..13275e3a --- /dev/null +++ b/custom-io-callbacks/file-server/check.sh @@ -0,0 +1,17 @@ +#!/bin/sh +./start-server $1 & +PID1=$! +RESULT1=$? + +cd ../file-client +./start-client $1 +PID2=$! +RESULT2=$? + +echo "RESULT1 = ${RESULT1}" +echo "" +echo "RESULT2 = ${RESULT2}" +echo "" +kill ${PID1} +kill ${PID2} + diff --git a/custom-io-callbacks/file-server/file-server.c b/custom-io-callbacks/file-server/file-server.c new file mode 100644 index 00000000..789805a1 --- /dev/null +++ b/custom-io-callbacks/file-server/file-server.c @@ -0,0 +1,276 @@ +/* file-server.c + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + * + * EXAMPLE DEFINIITON: + * + * Instead of using sockets we will show how it is possible + * to deliver TLS handshake and packet exchange through the use of + * the file system! We will accomplish this using the wolfSSL + * IO callbacks to read/write to files instead of using sockets + */ + +/*--------------------------------------------------------------*/ +/* Header files and definitions */ +/*--------------------------------------------------------------*/ +#ifdef HAVE_CONFIG_H + #include +#endif + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + + +#define MAXSZ 1024 +/* Use the certs already available in the examples repo */ +#define serverCert "../../certs/server-cert.pem" +#define serverKey "../../certs/server-key.pem" +#define CR "../file-client/client_read_server_write_file.txt" +#define SR "../file-client/client_write_server_read_file.txt" +/*--------------------------------------------------------------*/ +/* Function Prototypes and global variables */ +/*--------------------------------------------------------------*/ +unsigned int my_psk_server_cb(WOLFSSL* ssl, const char* identity, + unsigned char* Xkey, unsigned int key_max_len); + +int CbIOSend(WOLFSSL *ssl, char *buf, int sz, void *ctx); +int CbIORecv(WOLFSSL *ssl, char *buf, int sz, void *ctx); +int ConvertHexToBin(const char* h1, byte* b1, word32* b1Sz); +WOLFSSL* Server(WOLFSSL_CTX* ctx, char* suite, int setSuite); + +static int fpSend; +static int fpRecv; +static int verboseFlag = 0; +/*--------------------------------------------------------------*/ +/* Function implementations */ +/*--------------------------------------------------------------*/ +int CbIORecv(WOLFSSL *ssl, char *buf, int sz, void *ctx) +{ + int ret = 0; + int i; + while (ret <= 0) + ret = read(fpRecv, buf, sz); + if (verboseFlag == 1) { + printf("SERVER WANTS TO READ: %d bytes\n", sz); + printf("/*------------------- SERVER READING ------------------*/\n"); + for (i = 0; i < sz; i++) { + printf("%02x ", (unsigned char) buf[i]); + if (i > 0 && (i % 16) == 0) + printf("\n"); + } + printf("\n/*------------------- SERVER READING ------------------*/\n"); + } + return ret; +} + +int CbIOSend(WOLFSSL *ssl, char *buf, int sz, void *ctx) +{ + int ret; + int i; + ret = write(fpSend, buf, sz); + if (verboseFlag == 1) { + printf("/*------------------- SERVER SENDING ------------------*/\n"); + for (i = 0; i < sz; i++) { + printf("%02x ", (unsigned char) buf[i]); + if (i > 0 && (i % 16) == 0) + printf("\n"); + } + printf("\n/*------------------- SERVER SENDING ------------------*/\n"); + } + return ret; +} + + +WOLFSSL* Server(WOLFSSL_CTX* ctx, char* suite, int setSuite) +{ + WOLFSSL* ssl; + int ret = -1; + + if ((ctx = wolfSSL_CTX_new(wolfTLSv1_2_server_method())) == NULL) { + printf("Error in setting server ctx\n"); + return NULL; + } + +#ifndef NO_PSK + wolfSSL_CTX_SetTmpDH_buffer(ctx, dh_key_der_1024, sizeof_dh_key_der_1024, + SSL_FILETYPE_ASN1); +#endif + + if (wolfSSL_CTX_use_certificate_file(ctx, serverCert, SSL_FILETYPE_PEM) + != SSL_SUCCESS) { + printf("trouble loading server cert file\n"); + return NULL; + } + + if (wolfSSL_CTX_use_PrivateKey_file(ctx, serverKey, SSL_FILETYPE_PEM) + != SSL_SUCCESS) { + printf("trouble loading server key file\n"); + return NULL; + } + + if (setSuite == 1) { + if (( ret = wolfSSL_CTX_set_cipher_list(ctx, suite)) != SSL_SUCCESS) { + printf("ret = %d\n", ret); + printf("Error :can't set cipher\n"); + wolfSSL_CTX_free(ctx); + return NULL; + } + } else { + (void) suite; + } + + wolfSSL_SetIORecv(ctx, CbIORecv); + wolfSSL_SetIOSend(ctx, CbIOSend); + + if ((ssl = wolfSSL_new(ctx)) == NULL) { + printf("issue when creating ssl\n"); + wolfSSL_CTX_free(ctx); + return NULL; + } + + wolfSSL_set_fd(ssl, fpRecv); + wolfSSL_set_using_nonblock(ssl, fpRecv); + return ssl; +} + +int main(int argc, char** argv) +{ + char sMsg[] = "I hear you fashizzle\r\n"; + char reply[MAXSZ]; + int ret, msgSz; + WOLFSSL* sslServ; + WOLFSSL_CTX* ctxServ = NULL; + + if (argc == 2) { + if (XSTRNCMP(argv[1], "-verbose", 8) == 0 || + XSTRNCMP(argv[1], "-v", 2) == 0) { + verboseFlag = 1; + } + } + + fpSend = open(CR, O_WRONLY | O_NOCTTY | O_NDELAY); + fpRecv = open(SR, O_RDONLY | O_NOCTTY | O_NDELAY); + + if (verboseFlag == 1) { + wolfSSL_Debugging_ON(); + } + + wolfSSL_Init(); + InitMemoryTracker(); + + /* Example usage */ +// sslServ = Server(ctxServ, "ECDHE-RSA-AES128-SHA", 1); + sslServ = Server(ctxServ, "let-wolfssl-choose", 0); + + if (sslServ == NULL) { printf("sslServ NULL\n"); return 0;} + ret = SSL_FAILURE; + printf("Starting server\n"); + while (ret != SSL_SUCCESS) { + int error; + ret = wolfSSL_accept(sslServ); + error = wolfSSL_get_error(sslServ, 0); + if (ret != SSL_SUCCESS) { + if (error != SSL_ERROR_WANT_READ && + error != SSL_ERROR_WANT_WRITE) { + wolfSSL_free(sslServ); + wolfSSL_CTX_free(ctxServ); + printf("server ssl accept failed ret = %d error = %d wr = %d\n", + ret, error, SSL_ERROR_WANT_READ); + goto cleanup; + } + } + + } + + + /* read */ + while (1) { + int error; + + /* server send/read */ + memset(reply, 0, sizeof(reply)); + ret = wolfSSL_read(sslServ, reply, sizeof(reply) - 1); + error = wolfSSL_get_error(sslServ, 0); + if (ret < 0) { + if (error != SSL_ERROR_WANT_READ && + error != SSL_ERROR_WANT_WRITE) { + printf("server read failed\n"); + break; + } + } + else { + reply[ret] = 0; + printf("Server Received : %s\n", reply); + break; + } + } + + /* write */ + while (1) { + int error; + + msgSz = sizeof(sMsg); + ret = wolfSSL_write(sslServ, sMsg, msgSz); + error = wolfSSL_get_error(sslServ, 0); + if (ret != msgSz) { + if (error != SSL_ERROR_WANT_READ && + error != SSL_ERROR_WANT_WRITE) { + printf("server write failed\n"); + break; + } + } else if (ret == msgSz) { + printf("Server send successful\n"); + break; + } else { + printf("Unkown error occured, shutting down\n"); + break; + } + } + + +cleanup: + /* close the streams so client can reset file contents */ + close(fpRecv); + close(fpSend); + close(open(CR, O_RDWR | O_NOCTTY | O_NDELAY)); + close(open(SR, O_RDWR | O_NOCTTY | O_NDELAY)); + + ShowMemoryTracker(); + wolfSSL_shutdown(sslServ); + wolfSSL_free(sslServ); + wolfSSL_CTX_free(ctxServ); + wolfSSL_Cleanup(); + /* Reset the contents of the receive and send files for next run */ + fclose(fopen(SR, "wb")); + fclose(fopen(CR, "wb")); + + return -1; +}