diff --git a/.gitignore b/.gitignore index 4d40434d..9e76256c 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,32 @@ *.i*86 *.x86_64 *.hex + +# Example executables +/dtls/client-dtls-nonblocking +/dtls/client-dtls-resume +/dtls/client-dtls +/dtls/client-udp +/dtls/server-dtls-nonblocking +/dtls/server-dtls-threaded +/dtls/server-dtls +/dtls/server-udp + +/psk/client-psk-nonblocking +/psk/client-psk-resume +/psk/client-psk +/psk/client-tcp +/psk/server-psk-nonblocking +/psk/server-psk-threaded +/psk/server-psk +/psk/server-tcp + +/tls/client-tls-nonblocking +/tls/client-tls-resume +/tls/client-tls +/tls/client-tcp +/tls/server-tls-nonblocking +/tls/server-tls-threaded +/tls/server-tls +/tls/server-tcp + diff --git a/README.md b/README.md index 519f6362..bd06266a 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,78 @@ -wolfssl-examples -================ +wolfSSL Example Applications +============================ + +This repository contains example applications, written in C, which +demonstrate how to use the CyaSSL lightweight SSL/TLS library for secure +communication. + +Each directory represents a unique topic (SSL/TLS, DTLS, PSK, etc.) and +contains a Makefile as well as a simple tutorial on the given topic. + +## Current Examples + +#### DTLS (Datagram TLS) + +This directory contains examples of using DTLS, with client and server +examples demonstrating UDP, DTLS, non-blocking, session resumption, +and multi-threading. + +When compiling CyaSSL for use with these examples, CyaSSL will need to be +compiled with DTLS support: + +``` +cd cyassl-[version] +./configure --enable-dtls +``` + +Examples in this directory may be compiled using: + +``` +cd ./dtls +make +``` + +#### PSK (Pre-Shared Keys) + +This directory contains examples of using PSK, with client and server examples +demonstrating TCP/IP, PSK, non-blocking, session resumption, and +multi-threading. + +When compiling CyaSSL for use with these examples, CyaSSL will need to be +compiled with PSK support: + +``` +cd cyassl-[version] +./configure --enable-psk +``` + +Examples in this directory may be compiled using: + +``` +cd ./dtls +make +``` + +#### SSL/TLS + +This directory contains examples of using SSL/TLS, with client and server +examples demonstrating TCP/IP, SSL/TLS, non-blocking, session resumption, and +multi-threading. + +Examples in this directory may be compiled using: + +``` +cd ./dtls +make +``` + +## Notes + +When necessary, examples will use the example certificates and keys located +in the ./certs directory. These certificates and keys have been pulled in from +the main CyaSSL repository. + +## Support + +Please contact wolfSSL at support@wolfssl.com with any questions, bug fixes, +or suggested feature additions. -Example applications using the CyaSSL lightweight SSL/TLS library diff --git a/psk/tutorial-tcp-psk.md b/psk/tutorial-tcp-psk.md index 6cb3d76f..d6e0b28e 100644 --- a/psk/tutorial-tcp-psk.md +++ b/psk/tutorial-tcp-psk.md @@ -3,3 +3,227 @@ TCP/PSK Tutorial < TODO > + +# **Tutorial for adding Cyassl Security and PSK (Pre shared Keys) to a Simple Server.** + +1. Include the CyaSSL compatibility header: + +``` +#include +``` + +2. Change all calls from read() or recv() to CyaSSL_read(), in the simple server +``` + read(sockfd, recvline, MAXLINE) +becomes + CyaSSL_read(ssl, recvline, MAXLINE) +``` + * (CyaSSL_read on first use also calls CyaSSL_accept if not explicitly + called earlier in code.) + +3. Change all calls from write() or send() to CySSL_write(), in the simple client + +``` + write(sockfd, sendline, strlen(sendline)) +becomes +CyaSSL_write(ssl, sendline, strlen(sendline)) +``` + +4. Run the CyaSSL method to initalize CyaSSL + +``` + CyaSSL_Init() +``` +5. Create a ctx pointer that contains using the following process. + +``` + CYASSL_CTX* ctx; + + if ((ctx = CyaSSL_CTX_new(CyaSSLv23_server_method())) == NULL) + err_sys(“CyaSSL_CTX_new error”); +``` + +6. In the servers main loop for accepting clients create a CYASSL pointer. Once +a new client is accepted create a CyaSSL object and associate that object with +the socket that the client is on. After using the CyaSSL object it should be +freed and also before closing the program the ctx pointer should be freed and a +CyaSSL cleanup method called. + +``` + CYASSL* ssl; + + CyaSSL_set_fd(ssl, “integer returned from accept”); + + CyaSSL_free(ssl); + + CyaSSL_CTX_free(ctx); + CyaSSL_Cleanup(); +``` + + +# Now adding Pre-Shared Keys (PSK) to the CyaSSL Simple Server: + +1. Build CyaSSL with pre shared keys enabled executing the following commands +in CyaSSL’s root directory. Depending on file locations sudo may be needed when +running the commands. + +``` + ./configure --enable-psk + make + make install +``` + +2. Set up the psk suit with using the CyaSSL callback, identity hint, and cipher list methods. These methods get called immediately after the process of setting up ctx. + +``` + CyaSSL_CTX_set_psk_server_callback(ctx, my_psk_server_cb); + CyaSSL_CTX_use_psk_identity_hint(ctx, “cyassl server”); + CyaSSL_CTX_set_cipher_list(ctx, “PSK-AES128-CBC-SHA256”); +``` + + * PSK-AES128-CBC-SHA256 creates the cipher list of having pre shared keys + with advanced encryption security using 128 bit key with cipher block + chaining using secure hash algorithm. + + + + + + + + + + + + + +3. Add the my_psk_server_cb function as follows. This is a function needed that +is passed in as an argument to the CyaSSL callback. + +``` + static inline unsigned int my_psk_client_cb(CYASSL* ssl, char* identity, unsigned + char* key, unsigned int key_max_len) { + (void)ssl; + (void)key_max_len; + + if (strncmp(identity, "Client_identity", 15) != 0) + return 0; + + /* test key n hex is 0x1a2b3c4d , in decimal 439,041,101, we're using + * unsigned binary */ + key[0] = 26; + key[1] = 43; + key[2] = 60; + key[3] = 77; + + return 4; +} +``` + +Example Makefile for Simple Cyass PSK Client: + +``` +CC=gcc +OBJ = client-psk.o +CFLAG=-Wall + +%.o: %.c $(DEPS) +$(CC) -c -o $@ $< $(CFLAGS) + +client-psk: client-psk.c +$(CC) -Wall -o client-psk client-psk.c -lcyassl + +.PHONY: clean + +clean: + rm -f *.o client-psk +``` + +The -lcyassl will link the Cyassl Libraries to your program + + +The makefile for the server is going to be similar to that of the client. If +the user wants separate makefiles just make a use the same set up of the client +makefile and replace every instance of client-psk with server-psk. To combine +make files just add a server-psk with similar ending to each time client-psk is +referenced and change the target. There will also need to be a target for when +compiling all targets. +``` +all: server-psk client-psk + + server-psk: server-psk.c + $(CC) -Wall -o server-psk server-psk.c -lcyassl +``` + + + +# **Concurrent Server** + + +The main thread accepts clients and for each client accepted a new thread is +spawned that then handles the typical server processes. + + +1. To use multiple threads include the pthread header file. + **`#include `** + + +2. When creating multiple threads the state of variables can become an issue. +Since in the example, CYASSL_CTX* is not changed after being initially set we +can make it a global variable and allow all threads read access while they are +processing without having to lock the memory. + + +3. After the main thread accepts a client, call the pthread_create function. + +``` + pthread_create(pthread_t* thread, int attribute, void* function, void* arg) +``` + +4. In the example the function passed to pthread_create accepts one void * +argument which is the socket the client is on. The function then performs the +process of creating a new SSL object, reading and writing to the client, freeing +the SSL object, and then terminating the thread. + +``` + /* + *Process handled by a thread. + */ + void* cyassl_thread(void* fd) + { + CYASSL* ssl; + int connfd = (int)fd; + int n; /* length of string read */ + char buf[MAXLINE]; /* string read from client */ + char response[22] = "I hear ya for shizzle"; + + /* create CYASSL object and respond */ + if ((ssl = CyaSSL_new(ctx)) == NULL) + err_sys("CyaSSL_new error"); + CyaSSL_set_fd(ssl, connfd); + + /* respond to client */ + n = CyaSSL_read(ssl, buf, MAXLINE); + if (n > 0) { + printf("%s\n", buf); + if (CyaSSL_write(ssl, response, 22) > 22) { + err_sys("respond: write error"); + } + } + if (n < 0) { + err_sys("respond: read error"); + } + + /* closes the connections after responding */ + CyaSSL_shutdown(ssl); + CyaSSL_free(ssl); + if (close(connfd) == -1) + err_sys("close error"); + pthread_exit( NULL); + } +``` + +5. Void* arg is the argument that gets passed into cyassal_thread when +pthread_create is called. In this example that argument is used to pass the +socket value that the client for the current thread is on. + diff --git a/tls/Makefile b/tls/Makefile index 43552779..0569a55c 100644 --- a/tls/Makefile +++ b/tls/Makefile @@ -26,7 +26,7 @@ server-tls-nonblocking: server-tls-nonblocking.o $(CC) -o $@ $^ $(CFLAGS) $(LIBS) server-tls-threaded: server-tls-threaded.o - $(CC) -o $@ $^ $(CFLAGS) $(LIBS) + $(CC) -o $@ $^ $(CFLAGS) $(LIBS) -lpthread .PHONY: clean all diff --git a/tls/server-tcp.c b/tls/server-tcp.c index ed271e17..4fb7a560 100644 --- a/tls/server-tcp.c +++ b/tls/server-tcp.c @@ -34,14 +34,16 @@ #define DEFAULT_PORT 11111 -int AcceptAndRead(); +int AcceptAndRead(socklen_t sockfd); -int AcceptAndRead(int sockfd, struct sockaddr_in clientAddr) +int AcceptAndRead(socklen_t sockfd) { - int size = sizeof(clientAddr); + struct sockaddr_in clientAddr; + socklen_t size = sizeof(clientAddr); + int ret = 0; /* Wait until a client connects */ - int connd = accept(sockfd, (struct sockaddr *)&clientAddr, &size); + int connd = accept(sockfd,(struct sockaddr *)&clientAddr, &size); /* If fails to connect, loop back up and wait for a new connection */ if (connd == -1){ @@ -60,7 +62,7 @@ int AcceptAndRead(int sockfd, struct sockaddr_in clientAddr) bzero(&buff, sizeof(buff)); /* Read the client data into our buff array */ - if (read(connd, buff, sizeof(buff)-1) > 0){ + if ((ret = read(connd, buff, sizeof(buff)-1)) > 0){ /* Print any data the client sends to the console */ printf("Client: %s\n", buff); @@ -68,7 +70,8 @@ int AcceptAndRead(int sockfd, struct sockaddr_in clientAddr) char reply[] = "I hear ya fa shizzle!\n"; /* Reply back to the client */ - write(connd, reply, sizeof(reply)-1); + if ((ret = write(connd, reply, sizeof(reply)-1)) < 0) + printf("write error\n"); } /* If the client disconnects break the loop */ else @@ -92,17 +95,17 @@ int main() */ /* Identify and access the sockets */ - int sockfd = socket(AF_INET, SOCK_STREAM, 0); + socklen_t sockfd = socket(AF_INET, SOCK_STREAM, 0); int exit = 0; /* 0 = false, 1 = true */ /* If positive value, the socket is valid */ - if(sockfd < 0){ + if(sockfd == -1){ printf("ERROR: failed to create the socket\n"); return 1; /* Kill the server with exit status 1 */ } /* Server and client socket address structures */ - struct sockaddr_in serverAddr, clientAddr; + struct sockaddr_in serverAddr; /* Initialize the server address struct to zero */ memset((char *)&serverAddr, 0, sizeof(serverAddr)); @@ -125,7 +128,7 @@ int main() printf("Waiting for a connection...\n"); /* Accept client connections and read from them */ - exit = AcceptAndRead(sockfd, clientAddr); + exit = AcceptAndRead(sockfd); } /* Close the open sockets */ diff --git a/tls/server-tls-nonblocking.c b/tls/server-tls-nonblocking.c index 3a422d5a..d88c04df 100644 --- a/tls/server-tls-nonblocking.c +++ b/tls/server-tls-nonblocking.c @@ -43,14 +43,14 @@ */ enum read_write_t {WRITE, READ, ACCEPT}; -int AcceptAndRead(CYASSL_CTX* ctx, int socketfd, +int AcceptAndRead(CYASSL_CTX* ctx, socklen_t socketfd, struct sockaddr_in clientAddr); -int TCPSelect(int socketfd); -int NonBlocking_ReadWriteAccept(CYASSL* ssl, int socketfd, +int TCPSelect(socklen_t socketfd); +int NonBlocking_ReadWriteAccept(CYASSL* ssl, socklen_t socketfd, enum read_write_t rw); /* Check if any sockets are ready for reading and writing and set it */ -int TCPSelect(int socketfd) +int TCPSelect(socklen_t socketfd) { fd_set recvfds, errfds; int nfds = socketfd + 1; @@ -75,7 +75,7 @@ int TCPSelect(int socketfd) } /* Checks if NonBlocking I/O is wanted, if it is wanted it will * wait until it's available on the socket before reading or writing */ -int NonBlocking_ReadWriteAccept(CYASSL* ssl, int socketfd, +int NonBlocking_ReadWriteAccept(CYASSL* ssl, socklen_t socketfd, enum read_write_t rw) { const char reply[] = "I hear ya fa shizzle!\n"; @@ -144,12 +144,9 @@ int NonBlocking_ReadWriteAccept(CYASSL* ssl, int socketfd, return 1; } -int AcceptAndRead(CYASSL_CTX* ctx, int socketfd, struct sockaddr_in clientAddr) +int AcceptAndRead(CYASSL_CTX* ctx, socklen_t socketfd, struct sockaddr_in clientAddr) { - int size = sizeof(clientAddr); - int ret = 0; - int err = 0; - CYASSL* ssl; + socklen_t size = sizeof(clientAddr); /* Wait until a client connects */ int connd = accept(socketfd, (struct sockaddr *)&clientAddr, &size); @@ -161,7 +158,7 @@ int AcceptAndRead(CYASSL_CTX* ctx, int socketfd, struct sockaddr_in clientAddr) /* If it connects, read in and reply to the client */ else { printf("Client connected successfully!\n"); - + CYASSL* ssl; if ( (ssl = CyaSSL_new(ctx)) == NULL) { fprintf(stderr, "CyaSSL_new error.\n"); exit(EXIT_FAILURE); @@ -186,8 +183,8 @@ int AcceptAndRead(CYASSL_CTX* ctx, int socketfd, struct sockaddr_in clientAddr) if (NonBlocking_ReadWriteAccept(ssl, socketfd, WRITE) == 0) break; } + CyaSSL_free(ssl); /* Free the CYASSL object */ } - CyaSSL_free(ssl); /* Free the CYASSL object */ close(connd); /* close the connected socket */ return 0; @@ -201,9 +198,9 @@ int main() * Sets the type to be Stream based (TCP), * 0 means choose the default protocol. */ - int socketfd = socket(AF_INET, SOCK_STREAM, 0); + socklen_t socketfd = socket(AF_INET, SOCK_STREAM, 0); int loopExit = 0; /* 0 = False, 1 = True */ - int ret = 0; /* Return variable */ + int ret = 0; int on = 1; /* Set nonblocking */ @@ -226,7 +223,7 @@ int main() socklen_t len = sizeof(on); /* If positive value, the socket is valid */ - if (socketfd < 0) { + if (socketfd == -1) { printf("ERROR: failed to create the socket\n"); exit(EXIT_FAILURE); /* Kill the server with exit status 1 */ } @@ -245,7 +242,7 @@ int main() } /* Load server certificate into CYASSL_CTX */ - if (CyaSSL_CTX_use_certificate_file(ctx, "certs/server-cert.pem", + if (CyaSSL_CTX_use_certificate_file(ctx, "../certs/server-cert.pem", SSL_FILETYPE_PEM) != SSL_SUCCESS) { fprintf(stderr, "Error loading certs/server-cert.pem, please check" "the file.\n"); @@ -253,7 +250,7 @@ int main() } /* Load server key into CYASSL_CTX */ - if (CyaSSL_CTX_use_PrivateKey_file(ctx, "certs/server-key.pem", + if (CyaSSL_CTX_use_PrivateKey_file(ctx, "../certs/server-key.pem", SSL_FILETYPE_PEM) != SSL_SUCCESS) { fprintf(stderr, "Error loading certs/server-key.pem, please check" "the file.\n"); diff --git a/tls/server-tls-threaded.c b/tls/server-tls-threaded.c index 0c630700..98a1168b 100644 --- a/tls/server-tls-threaded.c +++ b/tls/server-tls-threaded.c @@ -39,7 +39,7 @@ #define DEFAULT_PORT 11111 -int AcceptAndRead(int sockfd, struct sockaddr_in clientAddr); +int AcceptAndRead(socklen_t sockfd, struct sockaddr_in clientAddr); void *ThreadHandler(void* socketDesc); /* Create a ctx pointer for our ssl */ @@ -93,12 +93,14 @@ void *ThreadHandler(void* socketDesc) break; } } + + exit(EXIT_SUCCESS); } -int AcceptAndRead(int sockfd, struct sockaddr_in clientAddr) +int AcceptAndRead(socklen_t sockfd, struct sockaddr_in clientAddr) { - int size = sizeof(clientAddr); + socklen_t size = sizeof(clientAddr); int connd; /* Identify and access the clients connection */ pthread_t thread_id; @@ -128,7 +130,7 @@ int main() * Sets the type to be Stream based (TCP), * 0 means choose the default protocol. */ - int sockfd = socket(AF_INET, SOCK_STREAM, 0); + socklen_t sockfd = socket(AF_INET, SOCK_STREAM, 0); int ret = 0; /* Return Variable */ int loopExit = 0; /* 0 = False, 1 = True */ @@ -147,7 +149,7 @@ int main() CyaSSL_Init(); /* If positive value, the socket is valid */ - if (sockfd < 0) { + if (sockfd == -1) { printf("ERROR: failed to create the socket\n"); return EXIT_FAILURE; } @@ -159,7 +161,7 @@ int main() } /* Load server certificate into CYASSL_CTX */ - if (CyaSSL_CTX_use_certificate_file(ctx, "certs/server-cert.pem", + if (CyaSSL_CTX_use_certificate_file(ctx, "../certs/server-cert.pem", SSL_FILETYPE_PEM) != SSL_SUCCESS) { fprintf(stderr, "Error loading certs/server-cert.pem, please check" "the file.\n"); @@ -167,7 +169,7 @@ int main() } /* Load server key into CYASSL_CTX */ - if (CyaSSL_CTX_use_PrivateKey_file(ctx, "certs/server-key.pem", + if (CyaSSL_CTX_use_PrivateKey_file(ctx, "../certs/server-key.pem", SSL_FILETYPE_PEM) != SSL_SUCCESS) { fprintf(stderr, "Error loading certs/server-key.pem, please check" "the file.\n"); diff --git a/tls/server-tls.c b/tls/server-tls.c index 06990477..5ad4483a 100644 --- a/tls/server-tls.c +++ b/tls/server-tls.c @@ -38,16 +38,15 @@ #define DEFAULT_PORT 11111 -int AcceptAndRead(CYASSL_CTX* ctx, int sockfd, struct sockaddr_in clientAddr); +int AcceptAndRead(CYASSL_CTX* ctx, socklen_t sockfd, struct sockaddr_in + clientAddr); -int AcceptAndRead(CYASSL_CTX* ctx, int sockfd, struct sockaddr_in clientAddr) +int AcceptAndRead(CYASSL_CTX* ctx, socklen_t sockfd, struct sockaddr_in + clientAddr) { /* Create our reply message */ const char reply[] = "I hear ya fa shizzle!\n"; - int size = sizeof(clientAddr); - int ret = 0; - int err = 0; - CYASSL* ssl; + socklen_t size = sizeof(clientAddr); /* Wait until a client connects */ int connd = accept(sockfd, (struct sockaddr *)&clientAddr, &size); @@ -59,6 +58,7 @@ int AcceptAndRead(CYASSL_CTX* ctx, int sockfd, struct sockaddr_in clientAddr) /* If it connects, read in and reply to the client */ else { printf("Client connected successfully\n"); + CYASSL* ssl; if ( (ssl = CyaSSL_new(ctx)) == NULL) { fprintf(stderr, "CyaSSL_new error.\n"); @@ -101,8 +101,8 @@ int AcceptAndRead(CYASSL_CTX* ctx, int sockfd, struct sockaddr_in clientAddr) break; } } + CyaSSL_free(ssl); /* Free the CYASSL object */ } - CyaSSL_free(ssl); /* Free the CYASSL object */ close(connd); /* close the connected socket */ return 0; @@ -119,7 +119,7 @@ int main() * Sets the type to be Stream based (TCP), * 0 means choose the default protocol. */ - int sockfd = socket(AF_INET, SOCK_STREAM, 0); + 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 */ @@ -129,7 +129,7 @@ int main() CyaSSL_Init(); /* If positive value, the socket is valid */ - if (sockfd < 0) { + if (sockfd == -1) { printf("ERROR: failed to create the socket\n"); return EXIT_FAILURE; /* Kill the server with exit status 1 */ } @@ -141,7 +141,7 @@ int main() } /* Load server certificate into CYASSL_CTX */ - if (CyaSSL_CTX_use_certificate_file(ctx, "certs/server-cert.pem", + if (CyaSSL_CTX_use_certificate_file(ctx, "../certs/server-cert.pem", SSL_FILETYPE_PEM) != SSL_SUCCESS) { fprintf(stderr, "Error loading certs/server-cert.pem, please check" "the file.\n"); @@ -149,7 +149,7 @@ int main() } /* Load server key into CYASSL_CTX */ - if (CyaSSL_CTX_use_PrivateKey_file(ctx, "certs/server-key.pem", + if (CyaSSL_CTX_use_PrivateKey_file(ctx, "../certs/server-key.pem", SSL_FILETYPE_PEM) != SSL_SUCCESS) { fprintf(stderr, "Error loading certs/server-key.pem, please check" "the file.\n"); diff --git a/tls/tutorial-tcp-tls.md b/tls/tutorial-tcp-tls.md index b36cb46d..07748bc6 100644 --- a/tls/tutorial-tcp-tls.md +++ b/tls/tutorial-tcp-tls.md @@ -1,6 +1,7 @@ TCP/TLS Tutorial ================ +<<<<<<< HEAD ## Client TLS Tutorial ### client-tls.c @@ -25,4 +26,6 @@ to '''c Security(sockfd); ''' -Now we just have to make the 'Security()' \ No newline at end of file +Now we just have to make the 'Security()' +======= +>>>>>>> a62664a86549dd488e2fa5ae902aa66da8b7a85d