diff --git a/dtls/bin-msgs/CH1.bin b/dtls/bin-msgs/CH1.bin new file mode 100644 index 00000000..e2ccb26a Binary files /dev/null and b/dtls/bin-msgs/CH1.bin differ diff --git a/dtls/bin-msgs/CH2.bin b/dtls/bin-msgs/CH2.bin new file mode 100644 index 00000000..648837c2 Binary files /dev/null and b/dtls/bin-msgs/CH2.bin differ diff --git a/dtls/client-dtls13.c b/dtls/client-dtls13.c index b58d70bb..2c7ae0e5 100644 --- a/dtls/client-dtls13.c +++ b/dtls/client-dtls13.c @@ -127,9 +127,16 @@ int main (int argc, char** argv) goto cleanup; } + showConnInfo(ssl); + /*****************************************************************************/ /* Code for sending datagram to server */ - if (fgets(sendLine, MAXLINE, stdin) != NULL) { + while (1) { + if (fgets(sendLine, MAXLINE, stdin) == NULL) + break; + + if (strncmp(sendLine, "end", 3) == 0) + break; /* Send sendLine to the server */ if (wolfSSL_write(ssl, sendLine, strlen(sendLine)) != strlen(sendLine)) { diff --git a/dtls/dtls-common.h b/dtls/dtls-common.h index c409b4ef..b1df4c63 100644 --- a/dtls/dtls-common.h +++ b/dtls/dtls-common.h @@ -19,9 +19,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA * - *============================================================================= - * - * Bare-bones example of a DTLS 1.3 client for instructional/learning purposes. */ #ifndef DTLS_COMMON_H_ @@ -29,45 +26,9 @@ #define INVALID_SOCKET (-1) -#define SFD_TIMEOUT_E (-1) -#define SFD_SOCKET_E (-2) -#define SFD_SELECT_E (-3) - -int wait_sfd(SOCKET_T socketfd, int to, int rx) { - fd_set fds, errfds; - fd_set* recvfds = NULL; - fd_set* sendfds = NULL; - SOCKET_T nfds = socketfd + 1; - struct timeval timeout; - int result; - - memset(&timeout, 0, sizeof(timeout)); - timeout.tv_sec = to; - - FD_ZERO(&fds); - FD_SET(socketfd, &fds); - FD_ZERO(&errfds); - FD_SET(socketfd, &errfds); - - if (rx) - recvfds = &fds; - else - sendfds = &fds; - - result = select(nfds, recvfds, sendfds, &errfds, &timeout); - - if (result == 0) - return SFD_TIMEOUT_E; - else if (result > 0) { - if (FD_ISSET(socketfd, &fds)) { - return 0; - } - else if(FD_ISSET(socketfd, &errfds)) - return SFD_SOCKET_E; - } - perror("select()"); - - return SFD_SELECT_E; +void showConnInfo(WOLFSSL* ssl) { + printf("New connection established using %s %s\n", + wolfSSL_get_version(ssl), wolfSSL_get_cipher(ssl)); } diff --git a/dtls/server-dtls.c b/dtls/server-dtls.c index 96c40b1b..5e4c13e8 100644 --- a/dtls/server-dtls.c +++ b/dtls/server-dtls.c @@ -175,25 +175,27 @@ int main(int argc, char** argv) printf("SSL_accept failed.\n"); break; } - if ((recvLen = wolfSSL_read(ssl, buff, sizeof(buff)-1)) > 0) { - printf("heard %d bytes\n", recvLen); + while (1) { + if ((recvLen = wolfSSL_read(ssl, buff, sizeof(buff)-1)) > 0) { + printf("heard %d bytes\n", recvLen); - buff[recvLen] = 0; - printf("I heard this: \"%s\"\n", buff); - } - else if (recvLen < 0) { - int readErr = wolfSSL_get_error(ssl, 0); - if(readErr != SSL_ERROR_WANT_READ) { - printf("SSL_read failed.\n"); - break; + buff[recvLen] = 0; + printf("I heard this: \"%s\"\n", buff); + } + else if (recvLen < 0) { + int readErr = wolfSSL_get_error(ssl, 0); + if(readErr != SSL_ERROR_WANT_READ) { + printf("SSL_read failed.\n"); + goto error; + } + } + if (wolfSSL_write(ssl, ack, sizeof(ack)) < 0) { + printf("wolfSSL_write fail.\n"); + goto error; + } + else { + printf("Sending reply.\n"); } - } - if (wolfSSL_write(ssl, ack, sizeof(ack)) < 0) { - printf("wolfSSL_write fail.\n"); - break; - } - else { - printf("Sending reply.\n"); } printf("reply sent \"%s\"\n", ack); @@ -207,8 +209,7 @@ int main(int argc, char** argv) printf("Client left cont to idle state\n"); } - /* With the "continue" keywords, it is possible for the loop to exit * - * without changing the value of cont */ +error: if (cleanup == 1) { wolfSSL_set_fd(ssl, 0); wolfSSL_shutdown(ssl); diff --git a/dtls/server-dtls13-event.c b/dtls/server-dtls13-event.c index 5f39bc8f..145d26a4 100644 --- a/dtls/server-dtls13-event.c +++ b/dtls/server-dtls13-event.c @@ -35,6 +35,7 @@ #include /* used for sockaddr_in */ #include #include +#include #include #include #include @@ -49,10 +50,11 @@ #define QUICK_MULT 4 /* Our quick timeout multiplier */ #define CHGOODCB_E (-1000) /* An error outside the range of wolfSSL * errors */ -#define CONN_TIMEOUT 5 /* How long we wait for peer data before +#define CONN_TIMEOUT 10 /* How long we wait for peer data before * closing the connection */ typedef struct conn_ctx { + struct conn_ctx* next; WOLFSSL* ssl; struct event* readEv; struct event* writeEv; @@ -63,14 +65,18 @@ WOLFSSL_CTX* ctx = NULL; struct event_base* base = NULL; WOLFSSL* pendingSSL = NULL; int listenfd = INVALID_SOCKET; /* Initialize our socket */ +conn_ctx* active = NULL; +struct event* newConnEvent = NULL; static void sig_handler(const int sig); static void free_resources(void); static void newConn(evutil_socket_t fd, short events, void* arg); static void dataReady(evutil_socket_t fd, short events, void* arg); static int chGoodCb(WOLFSSL* ssl, void*); +static int hsDoneCb(WOLFSSL* ssl, void*); static int newPendingSSL(void); static int newFD(void); +static void conn_ctx_free(conn_ctx* connCtx); int main(int argc, char** argv) { @@ -79,7 +85,6 @@ int main(int argc, char** argv) char servCertLoc[] = "../certs/server-cert.pem"; char servKeyLoc[] = "../certs/server-key.pem"; int exitVal = 1; - struct event* newConnEvent = NULL; /* Initialize wolfSSL before assigning ctx */ if (wolfSSL_Init() != WOLFSSL_SUCCESS) { @@ -206,24 +211,44 @@ cleanup: static int newPendingSSL(void) { + /* Applications should update this secret periodically */ + char *secret = "My secret"; + WOLFSSL* ssl; + /* Create the pending WOLFSSL Object */ - if ((pendingSSL = wolfSSL_new(ctx)) == NULL) { + if ((ssl = wolfSSL_new(ctx)) == NULL) { fprintf(stderr, "wolfSSL_new error.\n"); return 0; } - wolfSSL_dtls_set_using_nonblock(pendingSSL, 1); + wolfSSL_dtls_set_using_nonblock(ssl, 1); - if (wolfSSL_SetChGoodCb(pendingSSL, chGoodCb, NULL) != WOLFSSL_SUCCESS ) { + if (wolfSSL_SetChGoodCb(ssl, chGoodCb, NULL) != WOLFSSL_SUCCESS ) { fprintf(stderr, "wolfSSL_SetChGoodCb error.\n"); + wolfSSL_free(ssl); return 0; } - if (wolfSSL_set_fd(pendingSSL, listenfd) != WOLFSSL_SUCCESS) { - fprintf(stderr, "wolfSSL_set_fd error.\n"); + if (wolfSSL_SetHsDoneCb(ssl, hsDoneCb, NULL) != WOLFSSL_SUCCESS ) { + fprintf(stderr, "wolfSSL_SetHsDoneCb error.\n"); + wolfSSL_free(ssl); return 0; } + if (wolfSSL_set_fd(ssl, listenfd) != WOLFSSL_SUCCESS) { + fprintf(stderr, "wolfSSL_set_fd error.\n"); + wolfSSL_free(ssl); + return 0; + } + + if (wolfSSL_send_hrr_cookie(ssl, (byte*)secret, strlen(secret)) != WOLFSSL_SUCCESS) { + fprintf(stderr, "wolfSSL_set_fd error.\n"); + wolfSSL_free(ssl); + return 0; + } + + pendingSSL = ssl; + return 1; } @@ -281,28 +306,26 @@ static int chGoodCb(WOLFSSL* ssl, void* arg) int fd = INVALID_SOCKET; struct sockaddr_in cliaddr; /* the client's address */ socklen_t cliLen = sizeof(cliaddr); - conn_ctx* new_ctx = (conn_ctx*)calloc(1, sizeof(conn_ctx)); + conn_ctx* connCtx = (conn_ctx*)calloc(1, sizeof(conn_ctx)); int timeout = wolfSSL_dtls_get_current_timeout(ssl); struct timeval tv; (void)arg; - if (new_ctx == NULL) { + if (connCtx == NULL) { fprintf(stderr, "Out of memory!\n"); goto error; } - new_ctx->ssl = ssl; + /* Push to active connection stack */ + connCtx->next = active; + active = connCtx; if (wolfSSL_dtls_get_peer(ssl, &cliaddr, &cliLen) != WOLFSSL_SUCCESS) { fprintf(stderr, "wolfSSL_dtls_get_peer failed\n"); goto error; } - /* Promote the pending connection to an active connection */ - if (!newPendingSSL()) - goto error; - /* We need to change the sfd here so that the ssl object doesn't drop any * new connections */ fd = newFD(); @@ -327,13 +350,13 @@ static int chGoodCb(WOLFSSL* ssl, void* arg) goto error; } - new_ctx->writeEv = event_new(base, fd, EV_WRITE, dataReady, new_ctx); - if (new_ctx->writeEv == NULL) { + connCtx->writeEv = event_new(base, fd, EV_WRITE, dataReady, connCtx); + if (connCtx->writeEv == NULL) { fprintf(stderr, "event_new failed for srvEvent\n"); goto error; } - new_ctx->readEv = event_new(base, fd, EV_READ, dataReady, new_ctx); - if (new_ctx->readEv == NULL) { + connCtx->readEv = event_new(base, fd, EV_READ, dataReady, connCtx); + if (connCtx->readEv == NULL) { fprintf(stderr, "event_new failed for srvEvent\n"); goto error; } @@ -348,21 +371,37 @@ static int chGoodCb(WOLFSSL* ssl, void* arg) tv.tv_sec = timeout; /* We are using non-blocking sockets so we will definitely be waiting for * the peer. Start the timer now. */ - if (event_add(new_ctx->readEv, &tv) != 0) { + if (event_add(connCtx->readEv, &tv) != 0) { fprintf(stderr, "event_add failed\n"); goto error; } + /* Promote the pending connection to an active connection */ + if (!newPendingSSL()) + goto error; + connCtx->ssl = ssl; + return 0; error: if (fd != INVALID_SOCKET) { close(fd); fd = INVALID_SOCKET; } + if (connCtx != NULL) { + connCtx->ssl = NULL; + conn_ctx_free(connCtx); + } (void)wolfSSL_set_fd(ssl, INVALID_SOCKET); return CHGOODCB_E; } +static int hsDoneCb(WOLFSSL* ssl, void* arg) +{ + showConnInfo(ssl); + (void)arg; + return 0; +} + static void dataReady(evutil_socket_t fd, short events, void* arg) { conn_ctx* connCtx = (conn_ctx*)arg; @@ -400,7 +439,7 @@ static void dataReady(evutil_socket_t fd, short events, void* arg) if (connCtx->waitingOnData) { /* Too long waiting for peer data. Shutdown the connection. * Don't wait for a response from the peer. */ - printf("Closing connection after timeout"); + printf("Closing connection after timeout\n"); (void)wolfSSL_shutdown(connCtx->ssl); goto error; } @@ -476,18 +515,41 @@ static void dataReady(evutil_socket_t fd, short events, void* arg) return; error: /* Free the connection */ - (void)event_del(connCtx->readEv); - (void)event_del(connCtx->writeEv); - event_free(connCtx->readEv); /* EV_PERSIST not used so safe to free here */ - event_free(connCtx->writeEv); /* EV_PERSIST not used so safe to free here */ - wolfSSL_Free(connCtx->ssl); + conn_ctx_free(connCtx); close(fd); - free(connCtx); +} + +static void conn_ctx_free(conn_ctx* connCtx) +{ + if (connCtx != NULL) { + /* Remove from active stack */ + if (active != NULL) { + conn_ctx** prev = &active; + while (*prev != NULL) { + if (*prev == connCtx) { + *prev = connCtx->next; + break; + } + prev = &(*prev)->next; + } + } + if (connCtx->ssl != NULL) + wolfSSL_free(connCtx->ssl); + if (connCtx->readEv != NULL) { + (void)event_del(connCtx->readEv); + event_free(connCtx->readEv); + } + if (connCtx->writeEv != NULL) { + (void)event_del(connCtx->writeEv); + event_free(connCtx->writeEv); + } + free(connCtx); + } } void sig_handler(const int sig) { - (void)sig; + printf("Received signal %d. Cleaning up.\n", sig); free_resources(); wolfSSL_Cleanup(); exit(0); @@ -495,6 +557,12 @@ void sig_handler(const int sig) void free_resources(void) { + conn_ctx* connCtx = active; + while (connCtx != NULL) { + active = active->next; + conn_ctx_free(connCtx); + connCtx = active; + } if (pendingSSL != NULL) { wolfSSL_shutdown(pendingSSL); wolfSSL_free(pendingSSL); @@ -508,4 +576,13 @@ void free_resources(void) close(listenfd); listenfd = INVALID_SOCKET; } + if (newConnEvent != NULL) { + (void)event_del(newConnEvent); + event_free(newConnEvent); + newConnEvent = NULL; + } + if (base != NULL) { + event_base_free(base); + base = NULL; + } } diff --git a/dtls/server-dtls13.c b/dtls/server-dtls13.c index fc8d6621..8fb904ae 100644 --- a/dtls/server-dtls13.c +++ b/dtls/server-dtls13.c @@ -158,7 +158,7 @@ int main(int argc, char** argv) fprintf(stderr, "SSL_accept failed.\n"); goto cleanup; } - printf("Connected!\n"); + showConnInfo(ssl); if ((recvLen = wolfSSL_read(ssl, buff, sizeof(buff)-1)) > 0) { printf("heard %d bytes\n", recvLen);