diff --git a/.gitignore b/.gitignore index ab22d786e..dd4247fcc 100644 --- a/.gitignore +++ b/.gitignore @@ -51,6 +51,10 @@ examples/client/client examples/echoclient/echoclient examples/echoserver/echoserver examples/server/server +examples/sctp/sctp-server +examples/sctp/sctp-server-dtls +examples/sctp/sctp-client +examples/sctp/sctp-client-dtls server_ready snifftest output diff --git a/configure.ac b/configure.ac index fbb1481a0..2908f99e7 100644 --- a/configure.ac +++ b/configure.ac @@ -221,6 +221,29 @@ then fi +# DTLS-SCTP +AC_ARG_ENABLE([sctp], + [AS_HELP_STRING([--enable-sctp],[Enable wolfSSL DTLS-SCTP support (default: disabled)])], + [ENABLED_SCTP=$enableval], + [ENABLED_SCTP=no]) + +AM_CONDITIONAL([BUILD_SCTP], [test "x$ENABLED_SCTP" = "xyes"]) + +AS_IF([test "x$ENABLED_SCTP" = "xyes"], + [AC_MSG_CHECKING([for SCTP]) + AC_RUN_IFELSE( + [AC_LANG_PROGRAM( +[[ +#include +#include +]], +[[int s = socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP); if (s == -1) return 1;]])], +[AC_MSG_RESULT(yes)], +[AC_MSG_RESULT(no) + AC_MSG_ERROR([SCTP not available, remove enable-sctp from configure])]) +]) + + # OpenSSH compatibility Build AC_ARG_ENABLE([openssh], [AS_HELP_STRING([--enable-openssh],[Enable OpenSSH compatibility build (default: disabled)])], @@ -2886,6 +2909,15 @@ AS_IF([test "x$ENABLED_MAXSTRENGTH" = "xyes" && \ test "x$ENABLED_SSLV3" = "xyes"], [AC_MSG_ERROR([Cannot use Max Strength and SSLv3 at the same time.])]) +AS_IF([test "x$ENABLED_SCTP" = "xyes"], + [AM_CFLAGS="-DWOLFSSL_SCTP $AM_CFLAGS"]) + +# SCTP requires DTLS +AS_IF([test "x$ENABLED_DTLS" = "xno" && \ + test "x$ENABLED_SCTP" = "xyes"], + [AM_CFLAGS="-DWOLFSSL_DTLS $AM_CFLAGS" + ENABLED_DTLS=yes]) + ################################################################################ # OPTIMIZE FLAGS @@ -3147,6 +3179,7 @@ echo " * LIGHTY: $ENABLED_LIGHTY" echo " * STUNNEL: $ENABLED_STUNNEL" echo " * ERROR_STRINGS: $ENABLED_ERROR_STRINGS" echo " * DTLS: $ENABLED_DTLS" +echo " * SCTP: $ENABLED_SCTP" echo " * Old TLS Versions: $ENABLED_OLD_TLS" echo " * SSL version 3.0: $ENABLED_SSLV3" echo " * OCSP: $ENABLED_OCSP" diff --git a/examples/client/client.c b/examples/client/client.c index f814c0d4e..ae61c1a5f 100644 --- a/examples/client/client.c +++ b/examples/client/client.c @@ -156,8 +156,10 @@ static void ShowVersions(void) printf("3\n"); } -int ClientBenchmarkConnections(WOLFSSL_CTX* ctx, char* host, word16 port, - int doDTLS, int benchmark, int resumeSession) +/* Measures average time to create, connect and disconnect a connection (TPS). +Benchmark = number of connections. */ +static int ClientBenchmarkConnections(WOLFSSL_CTX* ctx, char* host, word16 port, + int dtlsUDP, int dtlsSCTP, int benchmark, int resumeSession) { /* time passed in number of connects give average */ int times = benchmark; @@ -180,7 +182,7 @@ int ClientBenchmarkConnections(WOLFSSL_CTX* ctx, char* host, word16 port, if (ssl == NULL) err_sys("unable to get SSL object"); - tcp_connect(&sockfd, host, port, doDTLS, ssl); + tcp_connect(&sockfd, host, port, dtlsUDP, dtlsSCTP, ssl); #ifndef NO_SESSION_CACHE if (benchResume) @@ -215,8 +217,9 @@ int ClientBenchmarkConnections(WOLFSSL_CTX* ctx, char* host, word16 port, return EXIT_SUCCESS; } -int ClientBenchmarkThroughput(WOLFSSL_CTX* ctx, char* host, word16 port, - int doDTLS, int throughput) +/* Measures throughput in kbps. Throughput = number of bytes */ +static int ClientBenchmarkThroughput(WOLFSSL_CTX* ctx, char* host, word16 port, + int dtlsUDP, int dtlsSCTP, int throughput) { double start, conn_time = 0, tx_time = 0, rx_time = 0; SOCKET_T sockfd; @@ -227,7 +230,7 @@ int ClientBenchmarkThroughput(WOLFSSL_CTX* ctx, char* host, word16 port, ssl = wolfSSL_new(ctx); if (ssl == NULL) err_sys("unable to get SSL object"); - tcp_connect(&sockfd, host, port, doDTLS, ssl); + tcp_connect(&sockfd, host, port, dtlsUDP, dtlsSCTP, ssl); if (wolfSSL_set_fd(ssl, sockfd) != SSL_SUCCESS) { err_sys("error in setting fd"); } @@ -343,7 +346,8 @@ const char* starttlsCmd[6] = { "QUIT\r\n", }; -int StartTLS_Init(SOCKET_T* sockfd) +/* Initiates the STARTTLS command sequence over TCP */ +static int StartTLS_Init(SOCKET_T* sockfd) { char tmpBuf[256]; @@ -399,7 +403,8 @@ int StartTLS_Init(SOCKET_T* sockfd) return SSL_SUCCESS; } -int SMTP_Shutdown(WOLFSSL* ssl, int wc_shutdown) +/* Closes down the SMTP connection */ +static int SMTP_Shutdown(WOLFSSL* ssl, int wc_shutdown) { int ret; char tmpBuf[256]; @@ -461,6 +466,10 @@ static void Usage(void) printf("-g Send server HTTP GET\n"); printf("-u Use UDP DTLS," " add -v 2 for DTLSv1, -v 3 for DTLSv1.2 (default)\n"); +#ifdef WOLFSSL_SCTP + printf("-G Use SCTP DTLS," + " add -v 2 for DTLSv1, -v 3 for DTLSv1.2 (default)\n"); +#endif printf("-m Match domain name in cert\n"); printf("-N Use Non-blocking sockets\n"); printf("-r Resume session\n"); @@ -551,6 +560,8 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) int benchmark = 0; int throughput = 0; int doDTLS = 0; + int dtlsUDP = 0; + int dtlsSCTP = 0; int matchName = 0; int doPeerCheck = 1; int nonBlocking = 0; @@ -640,7 +651,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #ifndef WOLFSSL_VXWORKS while ((ch = mygetopt(argc, argv, - "?gdeDusmNrwRitfxXUPCVh:p:v:l:A:c:k:Z:b:zS:F:L:ToO:aB:W:E:M:q:")) + "?gdeDuGsmNrwRitfxXUPCVh:p:v:l:A:c:k:Z:b:zS:F:L:ToO:aB:W:E:M:q:")) != -1) { switch (ch) { case '?' : @@ -670,7 +681,15 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) break; case 'u' : - doDTLS = 1; + doDTLS = 1; + dtlsUDP = 1; + break; + + case 'G' : + #ifdef WOLFSSL_SCTP + doDTLS = 1; + dtlsSCTP = 1; + #endif break; case 's' : @@ -1112,6 +1131,11 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) } } +#ifdef WOLFSSL_SCTP + if (dtlsSCTP) + wolfSSL_CTX_dtls_set_sctp(ctx); +#endif + #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) wolfSSL_CTX_set_default_passwd_cb(ctx, PasswordCallBack); #endif @@ -1212,14 +1236,16 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) if (benchmark) { ((func_args*)args)->return_code = - ClientBenchmarkConnections(ctx, host, port, doDTLS, benchmark, resumeSession); + ClientBenchmarkConnections(ctx, host, port, dtlsUDP, dtlsSCTP, + benchmark, resumeSession); wolfSSL_CTX_free(ctx); exit(EXIT_SUCCESS); } if(throughput) { ((func_args*)args)->return_code = - ClientBenchmarkThroughput(ctx, host, port, doDTLS, throughput); + ClientBenchmarkThroughput(ctx, host, port, dtlsUDP, dtlsSCTP, + throughput); wolfSSL_CTX_free(ctx); exit(EXIT_SUCCESS); } @@ -1305,7 +1331,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) } #endif - tcp_connect(&sockfd, host, port, doDTLS, ssl); + tcp_connect(&sockfd, host, port, dtlsUDP, dtlsSCTP, ssl); if (wolfSSL_set_fd(ssl, sockfd) != SSL_SUCCESS) { err_sys("error in setting fd"); } @@ -1484,7 +1510,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) } #endif - if (doDTLS == 0) { /* don't send alert after "break" command */ + if (dtlsUDP == 0) { /* don't send alert after "break" command */ ret = wolfSSL_shutdown(ssl); if (wc_shutdown && ret == SSL_SHUTDOWN_NOT_DONE) wolfSSL_shutdown(ssl); /* bidirectional shutdown */ @@ -1498,7 +1524,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #ifndef NO_SESSION_CACHE if (resumeSession) { - if (doDTLS) { + if (dtlsUDP) { #ifdef USE_WINDOWS_API Sleep(500); #elif defined(WOLFSSL_TIRTOS) @@ -1507,7 +1533,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) sleep(1); #endif } - tcp_connect(&sockfd, host, port, doDTLS, sslResume); + tcp_connect(&sockfd, host, port, dtlsUDP, dtlsSCTP, sslResume); if (wolfSSL_set_fd(sslResume, sockfd) != SSL_SUCCESS) { err_sys("error in setting fd"); } diff --git a/examples/client/client.h b/examples/client/client.h index 913339ac0..39456a4f5 100644 --- a/examples/client/client.h +++ b/examples/client/client.h @@ -26,21 +26,6 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args); -/* Measures average time to create, connect and disconnect a connection (TPS). -Benchmark = number of connections. */ -int ClientBenchmarkConnections(WOLFSSL_CTX* ctx, char* host, word16 port, - int doDTLS, int benchmark, int resumeSession); - -/* Measures throughput in kbps. Throughput = number of bytes */ -int ClientBenchmarkThroughput(WOLFSSL_CTX* ctx, char* host, word16 port, - int doDTLS, int throughput); - -/* Initiates the STARTTLS command sequence over TCP */ -int StartTLS_Init(SOCKET_T* sockfd); - -/* Closes down the SMTP connection */ -int SMTP_Shutdown(WOLFSSL* ssl, int wc_shutdown); - #endif /* WOLFSSL_CLIENT_H */ diff --git a/examples/echoclient/echoclient.c b/examples/echoclient/echoclient.c index 6cb836e6a..1c06efa83 100644 --- a/examples/echoclient/echoclient.c +++ b/examples/echoclient/echoclient.c @@ -180,7 +180,7 @@ void echoclient_test(void* args) #endif /* WOLFSSL_ASYNC_CRYPT */ ssl = SSL_new(ctx); - tcp_connect(&sockfd, yasslIP, port, doDTLS, ssl); + tcp_connect(&sockfd, yasslIP, port, doDTLS, 0, ssl); SSL_set_fd(ssl, sockfd); #if defined(USE_WINDOWS_API) && defined(CYASSL_DTLS) && defined(NO_MAIN_DRIVER) diff --git a/examples/echoserver/echoserver.c b/examples/echoserver/echoserver.c index d917c946b..432525806 100644 --- a/examples/echoserver/echoserver.c +++ b/examples/echoserver/echoserver.c @@ -136,7 +136,7 @@ THREAD_RETURN CYASSL_THREAD echoserver_test(void* args) fdOpenSession(Task_self()); #endif - tcp_listen(&sockfd, &port, useAnyAddr, doDTLS); + tcp_listen(&sockfd, &port, useAnyAddr, doDTLS, 0); #if defined(CYASSL_DTLS) method = CyaDTLSv1_2_server_method(); @@ -373,7 +373,7 @@ THREAD_RETURN CYASSL_THREAD echoserver_test(void* args) CyaSSL_free(ssl); CloseSocket(clientfd); #ifdef CYASSL_DTLS - tcp_listen(&sockfd, &port, useAnyAddr, doDTLS); + tcp_listen(&sockfd, &port, useAnyAddr, doDTLS, 0); SignalReady(args, port); #endif } diff --git a/examples/include.am b/examples/include.am index e06bc86a1..66b82b1cd 100644 --- a/examples/include.am +++ b/examples/include.am @@ -5,3 +5,4 @@ include examples/client/include.am include examples/echoclient/include.am include examples/echoserver/include.am include examples/server/include.am +include examples/sctp/include.am diff --git a/examples/sctp/include.am b/examples/sctp/include.am new file mode 100644 index 000000000..ae970b40b --- /dev/null +++ b/examples/sctp/include.am @@ -0,0 +1,38 @@ +# vim:ft=automake +# included from Top Level Makefile.am +# All paths should be given relative to the root + + +if BUILD_SCTP +if BUILD_EXAMPLE_SERVERS +noinst_PROGRAMS += \ + examples/sctp/sctp-server \ + examples/sctp/sctp-server-dtls +examples_sctp_sctp_server_SOURCES = examples/sctp/sctp-server.c +examples_sctp_sctp_server_LDADD = $(LIB_STATIC_ADD) +examples_sctp_sctp_server_dtls_SOURCES = examples/sctp/sctp-server-dtls.c +examples_sctp_sctp_server_dtls_LDADD = src/libwolfssl.la $(LIB_STATIC_ADD) +examples_sctp_sctp_server_dtls_DEPENDENCIES = src/libwolfssl.la +endif +if BUILD_EXAMPLE_CLIENTS +noinst_PROGRAMS += \ + examples/sctp/sctp-client \ + examples/sctp/sctp-client-dtls +examples_sctp_sctp_client_SOURCES = examples/sctp/sctp-client.c +examples_sctp_sctp_client_LDADD = $(LIB_STATIC_ADD) +examples_sctp_sctp_client_dtls_SOURCES = examples/sctp/sctp-client-dtls.c +examples_sctp_sctp_client_dtls_LDADD = src/libwolfssl.la $(LIB_STATIC_ADD) +examples_sctp_sctp_client_dtls_DEPENDENCIES = src/libwolfssl.la +endif +endif + +dist_example_DATA += \ + examples/sctp/sctp-server.c \ + examples/sctp/sctp-server-dtls.c \ + examples/sctp/sctp-client.c \ + examples/sctp/sctp-client-dtls.c +DISTCLEANFILES += \ + examples/sctp/.libs/sctp-server \ + examples/sctp/.libs/sctp-server-dtls \ + examples/sctp/.libs/sctp-client \ + examples/sctp/.libs/sctp-client-dtls diff --git a/examples/sctp/sctp-client-dtls.c b/examples/sctp/sctp-client-dtls.c new file mode 100644 index 000000000..f07051795 --- /dev/null +++ b/examples/sctp/sctp-client-dtls.c @@ -0,0 +1,125 @@ +/* sctp-client-dtls.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 + */ + + +/* sctp */ +#include +#include +#include +#include + +/* std */ +#include +#include +#include +#include + +/* wolfssl */ +#include +#include + + + +#define cacert "./certs/ca-cert.pem" + +static int err_sys(const char* msg) +{ + perror(msg); + exit(EXIT_FAILURE); +} + +int main() +{ + int sd = socket(PF_INET, SOCK_STREAM, IPPROTO_SCTP); + + if (sd < 0) + err_sys("sctp socket error"); + + struct sockaddr_in sa; + memset(&sa, 0, sizeof(sa)); + sa.sin_family = AF_INET; + sa.sin_addr.s_addr = inet_addr("127.0.0.1"); + sa.sin_port = htons(12345); + + int ret = connect(sd, (struct sockaddr*)&sa, sizeof(sa)); + if (ret < 0) + err_sys("sctp connect error"); + + const char* response = "hello there"; + char buffer[80]; + + WOLFSSL_CTX* ctx = wolfSSL_CTX_new(wolfDTLSv1_2_client_method()); + if (ctx == NULL) + err_sys("ctx new dtls client failed"); + + ret = wolfSSL_CTX_dtls_set_sctp(ctx); + if (ret != SSL_SUCCESS) + err_sys("set sctp mode failed"); + + ret = wolfSSL_CTX_load_verify_locations(ctx, cacert, NULL); + if (ret != SSL_SUCCESS) + err_sys("ca cert error"); + + WOLFSSL* ssl = wolfSSL_new(ctx); + if (ssl == NULL) + err_sys("ssl new dtls client failed"); + + wolfSSL_set_fd(ssl, sd); + + ret = wolfSSL_connect(ssl); + if (ret != SSL_SUCCESS) + err_sys("ssl connect failed"); + + printf("TLS version is %s\n", wolfSSL_get_version(ssl)); + printf("Cipher Suite is %s\n", + wolfSSL_CIPHER_get_name(wolfSSL_get_current_cipher(ssl))); + + wolfSSL_write(ssl, response, (int)strlen(response)); + int got = wolfSSL_read(ssl, buffer, sizeof(buffer)); + if (got > 0) { + buffer[got] = 0; + printf("server said: %s\n", buffer); + } + + unsigned char bigBuf[4096]; + unsigned int i; + + for (i = 0; i < (int)sizeof(bigBuf); i++) + bigBuf[i] = (unsigned char)(i & 0xFF); + wolfSSL_write(ssl, bigBuf, sizeof(bigBuf)); + memset(bigBuf, 0, sizeof(bigBuf)); + + wolfSSL_read(ssl, bigBuf, sizeof(bigBuf)); + for (i = 0; i < sizeof(bigBuf); i++) { + if (bigBuf[i] != (unsigned char)(i & 0xFF)) { + printf("big message check fail\n"); + break; + } + } + + wolfSSL_shutdown(ssl); + wolfSSL_free(ssl); + wolfSSL_CTX_free(ctx); + + close(sd); + + return 0; +} diff --git a/examples/sctp/sctp-client.c b/examples/sctp/sctp-client.c new file mode 100644 index 000000000..b601fa403 --- /dev/null +++ b/examples/sctp/sctp-client.c @@ -0,0 +1,64 @@ +/* sctp-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 + */ + + +/* sctp */ +#include +#include +#include +#include + +/* std */ +#include +#include +#include + +int main() +{ + int sd = socket(PF_INET, SOCK_STREAM, IPPROTO_SCTP); + + if (sd < 0) + perror("sctp socket error"); + + struct sockaddr_in sa; + memset(&sa, 0, sizeof(sa)); + sa.sin_family = AF_INET; + sa.sin_addr.s_addr = inet_addr("127.0.0.1"); + sa.sin_port = htons(12345); + + int ret = connect(sd, (struct sockaddr*)&sa, sizeof(sa)); + if (ret < 0) + perror("sctp connect error"); + + const char* msg = "hello sctp"; + char buffer[80]; + + send(sd, msg, strlen(msg), 0); + int got = (int)recv(sd, buffer, sizeof(buffer), 0); + if (got > 0) { + buffer[got] = 0; + printf("server said: %s\n", buffer); + } + + close(sd); + + return 0; +} diff --git a/examples/sctp/sctp-server-dtls.c b/examples/sctp/sctp-server-dtls.c new file mode 100644 index 000000000..e64c888db --- /dev/null +++ b/examples/sctp/sctp-server-dtls.c @@ -0,0 +1,124 @@ +/* sctp-server-dtls.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 + */ + + +/* sctp */ +#include +#include +#include + +/* std */ +#include +#include +#include +#include + +/* wolfssl */ +#include +#include + + + +#define key "./certs/server-key.pem" +#define cert "./certs/server-cert.pem" + +static int err_sys(const char* msg) +{ + perror(msg); + exit(EXIT_FAILURE); +} + +int main() +{ + int sd = socket(PF_INET, SOCK_STREAM, IPPROTO_SCTP); + + if (sd < 0) + err_sys("sctp socket error"); + + struct sockaddr_in sa; + memset(&sa, 0, sizeof(sa)); + sa.sin_family = AF_INET; + sa.sin_addr.s_addr = htonl(INADDR_ANY); + sa.sin_port = htons(12345); + + int ret = bind(sd, (struct sockaddr*)&sa, sizeof(sa)); + if (ret < 0) + err_sys("sctp bind error"); + + listen(sd, 3); + + int client_sd = accept(sd, NULL, NULL); + if (client_sd < 0) + err_sys("sctp accept error"); + + const char* response = "well hello to you"; + char buffer[80]; + + WOLFSSL_CTX* ctx = wolfSSL_CTX_new(wolfDTLSv1_2_server_method()); + if (ctx == NULL) + err_sys("ctx new dtls server failed"); + + ret = wolfSSL_CTX_dtls_set_sctp(ctx); + if (ret != SSL_SUCCESS) + err_sys("set sctp mode failed"); + + ret = wolfSSL_CTX_use_PrivateKey_file(ctx, key, SSL_FILETYPE_PEM); + if (ret != SSL_SUCCESS) + err_sys("use private key error"); + + ret = wolfSSL_CTX_use_certificate_file(ctx, cert, SSL_FILETYPE_PEM); + if (ret != SSL_SUCCESS) + err_sys("use cert error"); + + WOLFSSL* ssl = wolfSSL_new(ctx); + if (ssl == NULL) + err_sys("ssl new dtls server failed"); + + wolfSSL_set_fd(ssl, client_sd); + + ret = wolfSSL_accept(ssl); + if (ret != SSL_SUCCESS) + err_sys("ssl accept failed"); + + printf("TLS version is %s\n", wolfSSL_get_version(ssl)); + printf("Cipher Suite is %s\n", + wolfSSL_CIPHER_get_name(wolfSSL_get_current_cipher(ssl))); + + int got = wolfSSL_read(ssl, buffer, sizeof(buffer)); + if (got > 0) { + buffer[got] = 0; + printf("client said: %s\n", buffer); + } + wolfSSL_write(ssl, response, (int)strlen(response)); + + unsigned char bigBuf[4096]; + + wolfSSL_read(ssl, bigBuf, sizeof(bigBuf)); + wolfSSL_write(ssl, bigBuf, sizeof(bigBuf)); + + wolfSSL_shutdown(ssl); + wolfSSL_free(ssl); + wolfSSL_CTX_free(ctx); + + close(sd); + + return 0; +} diff --git a/examples/sctp/sctp-server.c b/examples/sctp/sctp-server.c new file mode 100644 index 000000000..fc0439d36 --- /dev/null +++ b/examples/sctp/sctp-server.c @@ -0,0 +1,70 @@ +/* sctp-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 + */ + + +/* sctp */ +#include +#include +#include + +/* std */ +#include +#include +#include + +int main() +{ + int sd = socket(PF_INET, SOCK_STREAM, IPPROTO_SCTP); + + if (sd < 0) + perror("sctp socket error"); + + struct sockaddr_in sa; + memset(&sa, 0, sizeof(sa)); + sa.sin_family = AF_INET; + sa.sin_addr.s_addr = htonl(INADDR_ANY); + sa.sin_port = htons(12345); + + int ret = bind(sd, (struct sockaddr*)&sa, sizeof(sa)); + if (ret < 0) + perror("sctp bind error"); + + listen(sd, 3); + + int client_sd = accept(sd, NULL, NULL); + if (client_sd < 0) + perror("sctp accept error"); + + const char* response = "hi there"; + char buffer[80]; + + int got = (int)recv(client_sd, buffer, sizeof(buffer), 0); + if (got > 0) { + buffer[got] = 0; + printf("client said: %s\n", buffer); + } + send(client_sd, response, strlen(response), 0); + + + close(sd); + + return 0; +} diff --git a/examples/server/server.c b/examples/server/server.c index 792fa5bfb..de3b09960 100644 --- a/examples/server/server.c +++ b/examples/server/server.c @@ -219,6 +219,10 @@ static void Usage(void) printf("-t Track wolfSSL memory use\n"); printf("-u Use UDP DTLS," " add -v 2 for DTLSv1, -v 3 for DTLSv1.2 (default)\n"); +#ifdef WOLFSSL_SCTP + printf("-G Use SCTP DTLS," + " add -v 2 for DTLSv1, -v 3 for DTLSv1.2 (default)\n"); +#endif printf("-f Fewer packets/group messages\n"); printf("-r Allow one client Resumption\n"); printf("-N Use Non-blocking sockets\n"); @@ -275,6 +279,8 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) int usePskPlus = 0; int useAnon = 0; int doDTLS = 0; + int dtlsUDP = 0; + int dtlsSCTP = 0; int needDH = 0; int useNtruKey = 0; int nonBlocking = 0; @@ -370,7 +376,7 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) useAnyAddr = 1; #else while ((ch = mygetopt(argc, argv, - "?jdbstnNufrawPIR:p:v:l:A:c:k:Z:S:oO:D:L:ieB:E:q:")) != -1) { + "?jdbstnNuGfrawPIR:p:v:l:A:c:k:Z:S:oO:D:L:ieB:E:q:")) != -1) { switch (ch) { case '?' : Usage(); @@ -404,6 +410,14 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) case 'u' : doDTLS = 1; + dtlsUDP = 1; + break; + + case 'G' : + #ifdef WOLFSSL_SCTP + doDTLS = 1; + dtlsSCTP = 1; + #endif break; case 'f' : @@ -563,6 +577,11 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) myoptind = 0; /* reset for test cases */ #endif /* !WOLFSSL_VXWORKS */ + /* Can only use DTLS over UDP or SCTP, can't do both. */ + if (dtlsUDP && dtlsSCTP) { + err_sys("Cannot use DTLS with both UDP and SCTP."); + } + /* sort out DTLS versus TLS versions */ if (version == CLIENT_INVALID_VERSION) { if (doDTLS) @@ -689,6 +708,11 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) if (fewerPackets) CyaSSL_CTX_set_group_messages(ctx); +#ifdef WOLFSSL_SCTP + if (dtlsSCTP) + wolfSSL_CTX_dtls_set_sctp(ctx); +#endif + #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) SSL_CTX_set_default_passwd_cb(ctx, PasswordCallBack); #endif @@ -821,13 +845,13 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) while (1) { /* allow resume option */ if(resumeCount > 1) { - if (doDTLS == 0) { + if (dtlsUDP == 0) { SOCKADDR_IN_T client; socklen_t client_len = sizeof(client); clientfd = accept(sockfd, (struct sockaddr*)&client, (ACCEPT_THIRD_T)&client_len); } else { - tcp_listen(&sockfd, &port, useAnyAddr, doDTLS); + tcp_listen(&sockfd, &port, useAnyAddr, dtlsUDP, dtlsSCTP); clientfd = sockfd; } if(WOLFSSL_SOCKET_IS_INVALID(clientfd)) { @@ -908,7 +932,7 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) readySignal->srfName = serverReadyFile; } tcp_accept(&sockfd, &clientfd, (func_args*)args, port, useAnyAddr, - doDTLS, serverReadyFile ? 1 : 0, doListen); + dtlsUDP, dtlsSCTP, serverReadyFile ? 1 : 0, doListen); doListen = 0; /* Don't listen next time */ if (SSL_set_fd(ssl, clientfd) != SSL_SUCCESS) { @@ -923,7 +947,7 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) #endif #ifdef WOLFSSL_DTLS - if (doDTLS) { + if (doDTLS && dtlsUDP) { SOCKADDR_IN_T cliaddr; byte b[1500]; int n; @@ -1039,7 +1063,7 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) Task_yield(); #endif - if (doDTLS == 0) { + if (dtlsUDP == 0) { ret = SSL_shutdown(ssl); if (wc_shutdown && ret == SSL_SHUTDOWN_NOT_DONE) SSL_shutdown(ssl); /* bidirectional shutdown */ diff --git a/src/internal.c b/src/internal.c index 81910b8a9..7e619daf9 100755 --- a/src/internal.c +++ b/src/internal.c @@ -195,6 +195,22 @@ static INLINE int IsEncryptionOn(WOLFSSL* ssl, int isSend) } +/* If SCTP is not enabled returns the state of the dtls option. + * If SCTP is enabled returns dtls && !sctp. */ +static INLINE int IsDtlsNotSctpMode(WOLFSSL* ssl) +{ + int result = ssl->options.dtls; + + if (result) { +#ifdef WOLFSSL_SCTP + result = !ssl->options.dtlsSctp; +#endif + } + + return result; +} + + #ifdef HAVE_QSH /* free all structs that where used with QSH */ static int QSH_FreeAll(WOLFSSL* ssl) @@ -1373,6 +1389,10 @@ int InitSSL_Ctx(WOLFSSL_CTX* ctx, WOLFSSL_METHOD* method, void* heap) ctx->devId = INVALID_DEVID; +#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_SCTP) + ctx->dtlsMtuSz = MAX_RECORD_SIZE; +#endif + #ifndef NO_CERTS ctx->cm = wolfSSL_CertManagerNew_ex(heap); if (ctx->cm == NULL) { @@ -3324,9 +3344,6 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx) ssl->IOCB_ReadCtx = &ssl->nxCtx; /* default NetX IO ctx, same for read */ ssl->IOCB_WriteCtx = &ssl->nxCtx; /* and write */ #endif -#ifdef WOLFSSL_DTLS - ssl->dtls_expected_rx = MAX_MTU; -#endif ssl->options.serverState = NULL_STATE; ssl->options.clientState = NULL_STATE; @@ -3336,9 +3353,17 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx) ssl->options.processReply = doProcessInit; #ifdef WOLFSSL_DTLS + #ifdef WOLFSSL_SCTP + ssl->options.dtlsSctp = ctx->dtlsSctp; + ssl->dtlsMtuSz = ctx->dtlsMtuSz; + ssl->dtls_expected_rx = ssl->dtlsMtuSz; + #else + ssl->dtls_expected_rx = MAX_MTU; + #endif ssl->dtls_timeout_init = DTLS_TIMEOUT_INIT; ssl->dtls_timeout_max = DTLS_TIMEOUT_MAX; ssl->dtls_timeout = ssl->dtls_timeout_init; + ssl->buffers.dtlsCtx.fd = -1; #endif #ifndef NO_OLD_TLS @@ -3348,10 +3373,6 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx) #endif -#ifdef WOLFSSL_DTLS - ssl->buffers.dtlsCtx.fd = -1; -#endif - ssl->cipher.ssl = ssl; #ifdef HAVE_TLS_EXTENSIONS @@ -4779,16 +4800,15 @@ retry: return -1; case WOLFSSL_CBIO_ERR_TIMEOUT: - if (ssl->options.dtls) { -#ifdef WOLFSSL_DTLS - if (!ssl->options.handShakeDone && - DtlsPoolTimeout(ssl) == 0 && - DtlsPoolSend(ssl) == 0) { + #ifdef WOLFSSL_DTLS + if (IsDtlsNotSctpMode(ssl) && + !ssl->options.handShakeDone && + DtlsPoolTimeout(ssl) == 0 && + DtlsPoolSend(ssl) == 0) { - goto retry; - } -#endif + goto retry; } + #endif return -1; default: @@ -5055,7 +5075,7 @@ static int GetRecordHeader(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } #ifdef WOLFSSL_DTLS - if (ssl->options.dtls && + if (IsDtlsNotSctpMode(ssl) && (!DtlsCheckWindow(&ssl->keys.dtls_state) || (ssl->options.handShakeDone && ssl->keys.dtls_state.curEpoch == 0))) { return SEQUENCE_ERROR; @@ -7427,7 +7447,8 @@ static int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, /* hello_request not hashed */ /* Also, skip hashing the client_hello message here for DTLS. It will be * hashed later if the DTLS cookie is correct. */ - if (type != hello_request && !(ssl->options.dtls && type == client_hello) && + if (type != hello_request && + !(IsDtlsNotSctpMode(ssl) && type == client_hello) && ssl->error != WC_PENDING_E) { ret = HashInput(ssl, input + *inOutIdx, size); if (ret != 0) return ret; @@ -7790,7 +7811,8 @@ static int DoDtlsHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx, } *inOutIdx += ssl->keys.padSz; } - ret = DtlsPoolSend(ssl); + if (IsDtlsNotSctpMode(ssl)) + ret = DtlsPoolSend(ssl); } else if (fragSz < size) { /* Since this branch is in order, but fragmented, dtls_msg_list will be @@ -9180,7 +9202,7 @@ int ProcessReply(WOLFSSL* ssl) ssl->buffers.inputBuffer.length = 0; ssl->buffers.inputBuffer.idx = 0; - if (ssl->options.dtlsHsRetain) { + if (IsDtlsNotSctpMode(ssl) && ssl->options.dtlsHsRetain) { ret = DtlsPoolSend(ssl); if (ret != 0) return ret; @@ -9282,11 +9304,11 @@ int ProcessReply(WOLFSSL* ssl) ssl->keys.decryptedCur = 1; } - if (ssl->options.dtls) { #ifdef WOLFSSL_DTLS + if (IsDtlsNotSctpMode(ssl)) { DtlsUpdateWindow(&ssl->keys.dtls_state); - #endif /* WOLFSSL_DTLS */ } + #endif /* WOLFSSL_DTLS */ WOLFSSL_MSG("received record layer msg"); @@ -9339,9 +9361,11 @@ int ProcessReply(WOLFSSL* ssl) if (ret != DUPLICATE_MSG_E && ret != OUT_OF_ORDER_E) return ret; - ret = DtlsPoolSend(ssl); - if (ret != 0) - return ret; + if (IsDtlsNotSctpMode(ssl)) { + ret = DtlsPoolSend(ssl); + if (ret != 0) + return ret; + } if (ssl->curSize != 1) { WOLFSSL_MSG("Malicious or corrupted" @@ -9532,7 +9556,7 @@ int SendChangeCipher(WOLFSSL* ssl) } #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) { + if (IsDtlsNotSctpMode(ssl)) { if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0) return ret; } @@ -9971,7 +9995,7 @@ int SendFinished(WOLFSSL* ssl) #endif #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) { + if (IsDtlsNotSctpMode(ssl)) { if ((ret = DtlsPoolSave(ssl, input, headerSz + finishedSz)) != 0) return ret; } @@ -10217,7 +10241,7 @@ int SendCertificate(WOLFSSL* ssl) } #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) { + if (IsDtlsNotSctpMode(ssl)) { if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0) return ret; } @@ -10312,7 +10336,7 @@ int SendCertificateRequest(WOLFSSL* ssl) i += REQ_HEADER_SZ; */ #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) { + if (IsDtlsNotSctpMode(ssl)) { if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0) return ret; } @@ -10411,7 +10435,7 @@ static int BuildCertificateStatus(WOLFSSL* ssl, byte type, buffer* status, ret = HashOutput(ssl, output, sendSz, 0); #ifdef WOLFSSL_DTLS - if (ret == 0 && ssl->options.dtls) + if (ret == 0 && IsDtlsNotSctpMode(ssl)) ret = DtlsPoolSave(ssl, output, sendSz); #endif @@ -10810,14 +10834,10 @@ int SendData(WOLFSSL* ssl, const void* data, int sz) #endif for (;;) { -#ifdef HAVE_MAX_FRAGMENT - int len = min(sz - sent, min(ssl->max_fragment, OUTPUT_RECORD_SIZE)); -#else - int len = min(sz - sent, OUTPUT_RECORD_SIZE); -#endif + int len; byte* out; byte* sendBuffer = (byte*)data + sent; /* may switch on comp */ - int buffSz = len; /* may switch on comp */ + int buffSz; /* may switch on comp */ int outputSz; #ifdef HAVE_LIBZ byte comp[MAX_RECORD_SIZE + MAX_COMP_EXTRA]; @@ -10825,12 +10845,17 @@ int SendData(WOLFSSL* ssl, const void* data, int sz) if (sent == sz) break; + len = min(sz - sent, OUTPUT_RECORD_SIZE); +#ifdef HAVE_MAX_FRAGMENT + len = min(len, ssl->max_fragment); +#endif + #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) { - len = min(len, MAX_UDP_SIZE); - buffSz = len; + if (IsDtlsNotSctpMode(ssl)) { + len = min(len, MAX_UDP_SIZE); } #endif + buffSz = len; /* check for available size */ outputSz = len + COMP_EXTRA + dtlsExtra + MAX_MSG_EXTRA; @@ -12818,7 +12843,7 @@ static void PickHashSigAlgo(WOLFSSL* ssl, } #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) { + if (IsDtlsNotSctpMode(ssl)) { if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0) return ret; } @@ -15274,7 +15299,7 @@ int SendClientKeyExchange(WOLFSSL* ssl) } #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) { + if (IsDtlsNotSctpMode(ssl)) { if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0) { goto exit_scke; } @@ -15751,7 +15776,7 @@ int SendCertificateVerify(WOLFSSL* ssl) } #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) { + if (IsDtlsNotSctpMode(ssl)) { ret = DtlsPoolSave(ssl, output, sendSz); } #endif @@ -16028,7 +16053,7 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, ssl->buffers.outputBuffer.length += sendSz; #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) { + if (IsDtlsNotSctpMode(ssl)) { if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0) return ret; } @@ -17352,7 +17377,7 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #endif /* HAVE_ECC */ #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) { + if (IsDtlsNotSctpMode(ssl)) { if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0) { goto exit_sske; } @@ -17819,7 +17844,7 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, XMEMCPY(&pv, input + i, OPAQUE16_LEN); ssl->chVersion = pv; /* store */ #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) { + if (IsDtlsNotSctpMode(ssl)) { int ret; #if defined(NO_SHA) && defined(NO_SHA256) #error "DTLS needs either SHA or SHA-256" @@ -17896,7 +17921,7 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, /* random */ XMEMCPY(ssl->arrays->clientRandom, input + i, RAN_LEN); #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) { + if (IsDtlsNotSctpMode(ssl)) { int ret = wc_HmacUpdate(&cookieHmac, input + i, RAN_LEN); if (ret != 0) return ret; } @@ -17929,7 +17954,7 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, XMEMCPY(ssl->arrays->sessionID, input + i, b); #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) { + if (IsDtlsNotSctpMode(ssl)) { int ret = wc_HmacUpdate(&cookieHmac, input + i - 1, b + 1); if (ret != 0) return ret; } @@ -17983,7 +18008,7 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, XMEMCPY(clSuites.suites, input + i, clSuites.suiteSz); #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) { + if (IsDtlsNotSctpMode(ssl)) { int ret = wc_HmacUpdate(&cookieHmac, input + i - OPAQUE16_LEN, clSuites.suiteSz + OPAQUE16_LEN); @@ -18000,7 +18025,7 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, return BUFFER_ERROR; #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) { + if (IsDtlsNotSctpMode(ssl)) { byte newCookie[MAX_COOKIE_LEN]; int ret; @@ -18535,7 +18560,7 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, AddHeaders(output, 0, server_hello_done, ssl); #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) { + if (IsDtlsNotSctpMode(ssl)) { if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0) return 0; } diff --git a/src/ssl.c b/src/ssl.c index ccda3ef24..61bd2d4f8 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -547,6 +547,61 @@ int wolfSSL_dtls_get_peer(WOLFSSL* ssl, void* peer, unsigned int* peerSz) return SSL_NOT_IMPLEMENTED; #endif } + + +#if defined(WOLFSSL_SCTP) && defined(WOLFSSL_DTLS) + +int wolfSSL_CTX_dtls_set_sctp(WOLFSSL_CTX* ctx) +{ + WOLFSSL_ENTER("wolfSSL_CTX_dtls_set_sctp()"); + + if (ctx == NULL) + return BAD_FUNC_ARG; + + ctx->dtlsSctp = 1; + return SSL_SUCCESS; +} + + +int wolfSSL_dtls_set_sctp(WOLFSSL* ssl) +{ + WOLFSSL_ENTER("wolfSSL_dtls_set_sctp()"); + + if (ssl == NULL) + return BAD_FUNC_ARG; + + ssl->options.dtlsSctp = 1; + return SSL_SUCCESS; +} + + +int wolfSSL_CTX_dtls_set_mtu(WOLFSSL_CTX* ctx, word16 newMtu) +{ + if (ctx == NULL || newMtu > MAX_RECORD_SIZE) + return BAD_FUNC_ARG; + + ctx->dtlsMtuSz = newMtu; + return SSL_SUCCESS; +} + + +int wolfSSL_dtls_set_mtu(WOLFSSL* ssl, word16 newMtu) +{ + if (ssl == NULL) + return BAD_FUNC_ARG; + + if (newMtu > MAX_RECORD_SIZE) { + ssl->error = BAD_FUNC_ARG; + return SSL_FAILURE; + } + + ssl->dtlsMtuSz = newMtu; + return SSL_SUCCESS; +} + + +#endif /* WOLFSSL_DTLS && WOLFSSL_SCTP */ + #endif /* WOLFSSL_LEANPSK */ @@ -1020,17 +1075,22 @@ static int wolfSSL_read_internal(WOLFSSL* ssl, void* data, int sz, int peek) #ifdef HAVE_ERRNO_H errno = 0; #endif + #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) + if (ssl->options.dtls) { ssl->dtls_expected_rx = max(sz + 100, MAX_MTU); +#ifdef WOLFSSL_SCTP + if (ssl->options.dtlsSctp) + ssl->dtls_expected_rx = max(ssl->dtls_expected_rx, ssl->dtlsMtuSz); +#endif + } #endif + sz = min(sz, OUTPUT_RECORD_SIZE); #ifdef HAVE_MAX_FRAGMENT - ret = ReceiveData(ssl, (byte*)data, - min(sz, min(ssl->max_fragment, OUTPUT_RECORD_SIZE)),peek); -#else - ret = ReceiveData(ssl, (byte*)data, min(sz, OUTPUT_RECORD_SIZE), peek); + sz = min(sz, ssl->max_fragment); #endif + ret = ReceiveData(ssl, (byte*)data, sz, peek); WOLFSSL_LEAVE("wolfSSL_read_internal()", ret); @@ -6753,6 +6813,21 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, } #endif + /* If SCTP is not enabled returns the state of the dtls option. + * If SCTP is enabled returns dtls && !sctp. */ + static INLINE int IsDtlsNotSctpMode(WOLFSSL* ssl) + { + int result = ssl->options.dtls; + + if (result) { + #ifdef WOLFSSL_SCTP + result = !ssl->options.dtlsSctp; + #endif + } + + return result; + } + /* please see note at top of README if you get an error from connect */ int wolfSSL_connect(WOLFSSL* ssl) { @@ -6822,7 +6897,7 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, /* In DTLS, when resuming, we can go straight to FINISHED, * or do a cookie exchange and then skip to FINISHED, assume * we need the cookie exchange first. */ - if (ssl->options.dtls) + if (IsDtlsNotSctpMode(ssl)) neededState = SERVER_HELLOVERIFYREQUEST_COMPLETE; #endif /* get response */ @@ -6834,7 +6909,7 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, /* if resumption failed, reset needed state */ else if (neededState == SERVER_FINISHED_COMPLETE) if (!ssl->options.resuming) { - if (!ssl->options.dtls) + if (!IsDtlsNotSctpMode(ssl)) neededState = SERVER_HELLODONE_COMPLETE; else neededState = SERVER_HELLOVERIFYREQUEST_COMPLETE; @@ -6849,7 +6924,7 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, return SSL_SUCCESS; #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) { + if (IsDtlsNotSctpMode(ssl)) { /* re-init hashes, exclude first hello and verify request */ #ifndef NO_OLD_TLS wc_InitMd5(&ssl->hsHashes->hashMd5); @@ -6894,7 +6969,7 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, case HELLO_AGAIN_REPLY : #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) { + if (IsDtlsNotSctpMode(ssl)) { neededState = ssl->options.resuming ? SERVER_FINISHED_COMPLETE : SERVER_HELLODONE_COMPLETE; diff --git a/tests/api.c b/tests/api.c index a24941698..11605d1ce 100644 --- a/tests/api.c +++ b/tests/api.c @@ -672,7 +672,7 @@ static THREAD_RETURN WOLFSSL_THREAD test_server_nofail(void* args) } ssl = wolfSSL_new(ctx); - tcp_accept(&sockfd, &clientfd, (func_args*)args, port, 0, 0, 0, 1); + tcp_accept(&sockfd, &clientfd, (func_args*)args, port, 0, 0, 0, 0, 1); CloseSocket(sockfd); if (wolfSSL_set_fd(ssl, clientfd) != SSL_SUCCESS) { @@ -800,7 +800,8 @@ static void test_client_nofail(void* args) } ssl = wolfSSL_new(ctx); - tcp_connect(&sockfd, wolfSSLIP, ((func_args*)args)->signal->port, 0, ssl); + tcp_connect(&sockfd, wolfSSLIP, ((func_args*)args)->signal->port, + 0, 0, ssl); if (wolfSSL_set_fd(ssl, sockfd) != SSL_SUCCESS) { /*err_sys("SSL_set_fd failed");*/ goto done2; @@ -919,14 +920,14 @@ static THREAD_RETURN WOLFSSL_THREAD run_wolfssl_server(void* args) socklen_t cliLen; cliLen = sizeof(cliAddr); - tcp_accept(&sfd, &cfd, (func_args*)args, port, 0, 1, 0, 0); + tcp_accept(&sfd, &cfd, (func_args*)args, port, 0, 1, 0, 0, 0); idx = (int)recvfrom(sfd, input, sizeof(input), MSG_PEEK, (struct sockaddr*)&cliAddr, &cliLen); AssertIntGT(idx, 0); wolfSSL_dtls_set_peer(ssl, &cliAddr, cliLen); } else { - tcp_accept(&sfd, &cfd, (func_args*)args, port, 0, 0, 0, 1); + tcp_accept(&sfd, &cfd, (func_args*)args, port, 0, 0, 0, 0, 1); CloseSocket(sfd); } @@ -1051,10 +1052,12 @@ static void run_wolfssl_client(void* args) ssl = wolfSSL_new(ctx); if (wolfSSL_dtls(ssl)) { - tcp_connect(&sfd, wolfSSLIP, ((func_args*)args)->signal->port, 1, ssl); + tcp_connect(&sfd, wolfSSLIP, ((func_args*)args)->signal->port, + 1, 0, ssl); } else { - tcp_connect(&sfd, wolfSSLIP, ((func_args*)args)->signal->port, 0, ssl); + tcp_connect(&sfd, wolfSSLIP, ((func_args*)args)->signal->port, + 0, 0, ssl); } AssertIntEQ(SSL_SUCCESS, wolfSSL_set_fd(ssl, sfd)); diff --git a/tests/suites.c b/tests/suites.c index c3864bd89..bc700d00e 100644 --- a/tests/suites.c +++ b/tests/suites.c @@ -513,6 +513,16 @@ int SuiteTest(void) exit(EXIT_FAILURE); } #endif +#ifdef WOLFSSL_SCTP + /* add dtls-sctp extra suites */ + strcpy(argv0[1], "tests/test-sctp.conf"); + printf("starting dtls-sctp extra cipher suite tests\n"); + test_harness(&args); + if (args.return_code != 0) { + printf("error from script %d\n", args.return_code); + exit(EXIT_FAILURE); + } +#endif #ifndef WC_STRICT_SIG #if !defined(NO_RSA) && defined(HAVE_ECC) /* testing mixed ECC/RSA cert */ /* add extra signature test suites */ diff --git a/tests/test-sctp.conf b/tests/test-sctp.conf new file mode 100644 index 000000000..26fe6fd7c --- /dev/null +++ b/tests/test-sctp.conf @@ -0,0 +1,1111 @@ +# server DTLSv1 DHE-RSA-CHACHA20-POLY1305 +-G +-v 2 +-l DHE-RSA-CHACHA20-POLY1305 + +# client DTLSv1 DHE-RSA-CHACHA20-POLY1305 +-G +-v 2 +-l DHE-RSA-CHACHA20-POLY1305 + +# server DTLSv1 ECDHE-RSA-CHACHA20-POLY1305 +-G +-v 2 +-l ECDHE-RSA-CHACHA20-POLY1305 + +# client DTLSv1 ECDHE-RSA-CHACHA20-POLY1305 +-G +-v 2 +-l ECDHE-RSA-CHACHA20-POLY1305 + +# server DTLSv1 ECDHE-EDCSA-CHACHA20-POLY1305 +-G +-v 2 +-l ECDHE-ECDSA-CHACHA20-POLY1305 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1 ECDHE-ECDSA-CHACHA20-POLY1305 +-G +-v 2 +-l ECDHE-ECDSA-CHACHA20-POLY1305 +-A ./certs/server-ecc.pem + +# server DTLSv1.2 DHE-RSA-CHACHA20-POLY1305 +-G +-v 3 +-l DHE-RSA-CHACHA20-POLY1305 + +# client DTLSv1.2 DHE-RSA-CHACHA20-POLY1305 +-G +-v 3 +-l DHE-RSA-CHACHA20-POLY1305 + +# server DTLSv1.2 ECDHE-RSA-CHACHA20-POLY1305 +-G +-v 3 +-l ECDHE-RSA-CHACHA20-POLY1305 + +# client DTLSv1.2 ECDHE-RSA-CHACHA20-POLY1305 +-G +-v 3 +-l ECDHE-RSA-CHACHA20-POLY1305 + +# server DTLSv1.2 ECDHE-EDCSA-CHACHA20-POLY1305 +-G +-v 3 +-l ECDHE-ECDSA-CHACHA20-POLY1305 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDHE-ECDSA-CHACHA20-POLY1305 +-G +-v 3 +-l ECDHE-ECDSA-CHACHA20-POLY1305 +-A ./certs/server-ecc.pem + +# server TLSv1.2 DHE-PSK-CHACHA20-POLY1305 +-G +-v 3 +-s +-l DHE-PSK-CHACHA20-POLY1305 + +# client TLSv1.2 DHE-PSK-CHACHA20-POLY1305 +-G +-v 3 +-s +-l DHE-PSK-CHACHA20-POLY1305 + +# server TLSv1.2 ECDHE-PSK-CHACHA20-POLY1305 +-G +-v 3 +-s +-l ECDHE-PSK-CHACHA20-POLY1305 + +# client TLSv1.2 ECDHE-PSK-CHACHA20-POLY1305 +-G +-v 3 +-s +-l ECDHE-PSK-CHACHA20-POLY1305 + +# server TLSv1.2 PSK-CHACHA20-POLY1305 +-G +-v 3 +-s +-l PSK-CHACHA20-POLY1305 + +# client TLSv1.2 PSK-CHACHA20-POLY1305 +-G +-v 3 +-s +-l PSK-CHACHA20-POLY1305 + +# server DTLSv1.2 DHE-RSA-CHACHA20-POLY1305-OLD +-G +-v 3 +-l DHE-RSA-CHACHA20-POLY1305-OLD + +# client DTLSv1.2 DHE-RSA-CHACHA20-POLY1305-OLD +-G +-v 3 +-l DHE-RSA-CHACHA20-POLY1305-OLD + +# server DTLSv1.2 ECDHE-RSA-CHACHA20-POLY1305-OLD +-G +-v 3 +-l ECDHE-RSA-CHACHA20-POLY1305-OLD + +# client DTLSv1.2 ECDHE-RSA-CHACHA20-POLY1305-OLD +-G +-v 3 +-l ECDHE-RSA-CHACHA20-POLY1305-OLD + +# server DTLSv1.2 ECDHE-EDCSA-CHACHA20-POLY1305-OLD +-G +-v 3 +-l ECDHE-ECDSA-CHACHA20-POLY1305-OLD +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDHE-ECDSA-CHACHA20-POLY1305-OLD +-G +-v 3 +-l ECDHE-ECDSA-CHACHA20-POLY1305-OLD +-A ./certs/server-ecc.pem + +# server DTLSv1 RC4-SHA +-G +-v 2 +-l RC4-SHA + +# client DTLSv1 RC4-SHA +-G +-v 2 +-l RC4-SHA + +# server DTLSv1.2 RC4-SHA +-G +-v 3 +-l RC4-SHA + +# client DTLSv1.2 RC4-SHA +-G +-v 3 +-l RC4-SHA + +# server DTLSv1 IDEA-CBC-SHA +-G +-v 2 +-l IDEA-CBC-SHA + +# client DTLSv1 IDEA-CBC-SHA +-G +-v 2 +-l IDEA-CBC-SHA + +# server DTLSv1 DES-CBC3-SHA +-G +-v 2 +-l DES-CBC3-SHA + +# client DTLSv1 DES-CBC3-SHA +-G +-v 2 +-l DES-CBC3-SHA + +# server DTLSv1.2 DES-CBC3-SHA +-G +-v 3 +-l DES-CBC3-SHA + +# client DTLSv1.2 DES-CBC3-SHA +-G +-v 3 +-l DES-CBC3-SHA + +# server DTLSv1 AES128-SHA +-G +-v 2 +-l AES128-SHA + +# client DTLSv1 AES128-SHA +-G +-v 2 +-l AES128-SHA + +# server DTLSv1.2 AES128-SHA +-G +-v 3 +-l AES128-SHA + +# client DTLSv1.2 AES128-SHA +-G +-v 3 +-l AES128-SHA + +# server DTLSv1 AES256-SHA +-G +-v 2 +-l AES256-SHA + +# client DTLSv1 AES256-SHA +-G +-v 2 +-l AES256-SHA + +# server DTLSv1.2 AES256-SHA +-G +-v 3 +-l AES256-SHA + +# client DTLSv1.2 AES256-SHA +-G +-v 3 +-l AES256-SHA + +# server DTLSv1 AES128-SHA256 +-G +-v 2 +-l AES128-SHA256 + +# client DTLSv1 AES128-SHA256 +-G +-v 2 +-l AES128-SHA256 + +# server DTLSv1.2 AES128-SHA256 +-G +-v 3 +-l AES128-SHA256 + +# client DTLSv1.2 AES128-SHA256 +-G +-v 3 +-l AES128-SHA256 + +# server DTLSv1 AES256-SHA256 +-G +-v 2 +-l AES256-SHA256 + +# client DTLSv1 AES256-SHA256 +-G +-v 2 +-l AES256-SHA256 + +# server DTLSv1.2 AES256-SHA256 +-G +-v 3 +-l AES256-SHA256 + +# client DTLSv1.2 AES256-SHA256 +-G +-v 3 +-l AES256-SHA256 + +# server DTLSv1 ECDHE-RSA-RC4 +-G +-v 2 +-l ECDHE-RSA-RC4-SHA + +# client DTLSv1 ECDHE-RSA-RC4 +-G +-v 2 +-l ECDHE-RSA-RC4-SHA + +# server DTLSv1.1 ECDHE-RSA-DES3 +-G +-v 2 +-l ECDHE-RSA-DES-CBC3-SHA + +# client DTLSv1.1 ECDHE-RSA-DES3 +-G +-v 2 +-l ECDHE-RSA-DES-CBC3-SHA + +# server DTLSv1.1 ECDHE-RSA-AES128 +-G +-v 2 +-l ECDHE-RSA-AES128-SHA + +# client DTLSv1.1 ECDHE-RSA-AES128 +-G +-v 2 +-l ECDHE-RSA-AES128-SHA + +# server DTLSv1.1 ECDHE-RSA-AES256 +-G +-v 2 +-l ECDHE-RSA-AES256-SHA + +# client DTLSv1.1 ECDHE-RSA-AES256 +-G +-v 2 +-l ECDHE-RSA-AES256-SHA + +# server DTLSv1.2 ECDHE-RSA-RC4 +-G +-v 3 +-l ECDHE-RSA-RC4-SHA + +# client DTLSv1.2 ECDHE-RSA-RC4 +-G +-v 3 +-l ECDHE-RSA-RC4-SHA + +# server DTLSv1.2 ECDHE-RSA-DES3 +-G +-v 3 +-l ECDHE-RSA-DES-CBC3-SHA + +# client DTLSv1.2 ECDHE-RSA-DES3 +-G +-v 3 +-l ECDHE-RSA-DES-CBC3-SHA + +# server DTLSv1.2 ECDHE-RSA-AES128 +-G +-v 3 +-l ECDHE-RSA-AES128-SHA + +# client DTLSv1.2 ECDHE-RSA-AES128 +-G +-v 3 +-l ECDHE-RSA-AES128-SHA + +# server DTLSv1.2 ECDHE-RSA-AES128-SHA256 +-G +-v 3 +-l ECDHE-RSA-AES128-SHA256 + +# client DTLSv1.2 ECDHE-RSA-AES128-SHA256 +-G +-v 3 +-l ECDHE-RSA-AES128-SHA256 + +# server DTLSv1.2 ECDHE-RSA-AES256 +-G +-v 3 +-l ECDHE-RSA-AES256-SHA + +# client DTLSv1.2 ECDHE-RSA-AES256 +-G +-v 3 +-l ECDHE-RSA-AES256-SHA + +# server TLSv1 ECDHE-ECDSA-NULL-SHA +-G +-v 1 +-l ECDHE-ECDSA-NULL-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1 ECDHE-ECDSA-NULL-SHA +-G +-v 1 +-l ECDHE-ECDSA-NULL-SHA +-A ./certs/server-ecc.pem + +# server TLSv1.1 ECDHE-ECDSA-NULL-SHA +-G +-v 2 +-l ECDHE-ECDSA-NULL-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1 ECDHE-ECDSA-NULL-SHA +-G +-v 2 +-l ECDHE-ECDSA-NULL-SHA +-A ./certs/server-ecc.pem + +# server TLSv1.2 ECDHE-ECDSA-NULL-SHA +-G +-v 3 +-l ECDHE-ECDSA-NULL-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1.2 ECDHE-ECDSA-NULL-SHA +-G +-v 3 +-l ECDHE-ECDSA-NULL-SHA +-A ./certs/server-ecc.pem + +# server DTLSv1.1 ECDHE-EDCSA-RC4 +-G +-v 2 +-l ECDHE-ECDSA-RC4-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.1 ECDHE-ECDSA-RC4 +-G +-v 2 +-l ECDHE-ECDSA-RC4-SHA +-A ./certs/server-ecc.pem + +# server DTLSv1.1 ECDHE-ECDSA-DES3 +-G +-v 2 +-l ECDHE-ECDSA-DES-CBC3-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.1 ECDHE-ECDSA-DES3 +-G +-v 2 +-l ECDHE-ECDSA-DES-CBC3-SHA +-A ./certs/server-ecc.pem + +# server DTLSv1.1 ECDHE-ECDSA-AES128 +-G +-v 2 +-l ECDHE-ECDSA-AES128-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.1 ECDHE-ECDSA-AES128 +-G +-v 2 +-l ECDHE-ECDSA-AES128-SHA +-A ./certs/server-ecc.pem + +# server DTLSv1.1 ECDHE-ECDSA-AES256 +-G +-v 2 +-l ECDHE-ECDSA-AES256-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.1 ECDHE-ECDSA-AES256 +-G +-v 2 +-l ECDHE-ECDSA-AES256-SHA +-A ./certs/server-ecc.pem + +# server DTLSv1.2 ECDHE-ECDSA-RC4 +-G +-v 3 +-l ECDHE-ECDSA-RC4-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDHE-ECDSA-RC4 +-G +-v 3 +-l ECDHE-ECDSA-RC4-SHA +-A ./certs/server-ecc.pem + +# server DTLSv1.2 ECDHE-ECDSA-DES3 +-G +-v 3 +-l ECDHE-ECDSA-DES-CBC3-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDHE-ECDSA-DES3 +-G +-v 3 +-l ECDHE-ECDSA-DES-CBC3-SHA +-A ./certs/server-ecc.pem + +# server DTLSv1.2 ECDHE-ECDSA-AES128 +-G +-v 3 +-l ECDHE-ECDSA-AES128-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDHE-ECDSA-AES128 +-G +-v 3 +-l ECDHE-ECDSA-AES128-SHA +-A ./certs/server-ecc.pem + +# server DTLSv1.2 ECDHE-ECDSA-AES128-SHA256 +-G +-v 3 +-l ECDHE-ECDSA-AES128-SHA256 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDHE-ECDSA-AES128-SHA256 +-G +-v 3 +-l ECDHE-ECDSA-AES128-SHA256 +-A ./certs/server-ecc.pem + +# server DTLSv1.2 ECDHE-ECDSA-AES256 +-G +-v 3 +-l ECDHE-ECDSA-AES256-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDHE-ECDSA-AES256 +-G +-v 3 +-l ECDHE-ECDSA-AES256-SHA +-A ./certs/server-ecc.pem + +# server DTLSv1.1 ECDH-RSA-RC4 +-G +-v 2 +-l ECDH-RSA-RC4-SHA +-c ./certs/server-ecc-rsa.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.1 ECDH-RSA-RC4 +-G +-v 2 +-l ECDH-RSA-RC4-SHA + +# server DTLSv1.1 ECDH-RSA-DES3 +-G +-v 2 +-l ECDH-RSA-DES-CBC3-SHA +-c ./certs/server-ecc-rsa.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.1 ECDH-RSA-DES3 +-G +-v 2 +-l ECDH-RSA-DES-CBC3-SHA + +# server DTLSv1.1 ECDH-RSA-AES128 +-G +-v 2 +-l ECDH-RSA-AES128-SHA +-c ./certs/server-ecc-rsa.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.1 ECDH-RSA-AES128 +-G +-v 2 +-l ECDH-RSA-AES128-SHA + +# server DTLSv1.1 ECDH-RSA-AES256 +-G +-v 2 +-l ECDH-RSA-AES256-SHA +-c ./certs/server-ecc-rsa.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.1 ECDH-RSA-AES256 +-G +-v 2 +-l ECDH-RSA-AES256-SHA + +# server DTLSv1.2 ECDH-RSA-RC4 +-G +-v 3 +-l ECDH-RSA-RC4-SHA +-c ./certs/server-ecc-rsa.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDH-RSA-RC4 +-G +-v 3 +-l ECDH-RSA-RC4-SHA + +# server DTLSv1.2 ECDH-RSA-DES3 +-G +-v 3 +-l ECDH-RSA-DES-CBC3-SHA +-c ./certs/server-ecc-rsa.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDH-RSA-DES3 +-G +-v 3 +-l ECDH-RSA-DES-CBC3-SHA + +# server DTLSv1.2 ECDH-RSA-AES128 +-G +-v 3 +-l ECDH-RSA-AES128-SHA +-c ./certs/server-ecc-rsa.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDH-RSA-AES128 +-G +-v 3 +-l ECDH-RSA-AES128-SHA + +# server DTLSv1.2 ECDH-RSA-AES128-SHA256 +-G +-v 3 +-l ECDH-RSA-AES128-SHA256 +-c ./certs/server-ecc-rsa.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDH-RSA-AES128-SHA256 +-G +-v 3 +-l ECDH-RSA-AES128-SHA256 + +# server DTLSv1.2 ECDH-RSA-AES256 +-G +-v 3 +-l ECDH-RSA-AES256-SHA +-c ./certs/server-ecc-rsa.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDH-RSA-AES256 +-G +-v 3 +-l ECDH-RSA-AES256-SHA + +# server DTLSv1.1 ECDH-EDCSA-RC4 +-G +-v 2 +-l ECDH-ECDSA-RC4-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.1 ECDH-ECDSA-RC4 +-G +-v 2 +-l ECDH-ECDSA-RC4-SHA +-A ./certs/server-ecc.pem + +# server DTLSv1.1 ECDH-ECDSA-DES3 +-G +-v 2 +-l ECDH-ECDSA-DES-CBC3-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.1 ECDH-ECDSA-DES3 +-G +-v 2 +-l ECDH-ECDSA-DES-CBC3-SHA +-A ./certs/server-ecc.pem + +# server DTLSv1.1 ECDH-ECDSA-AES128 +-G +-v 2 +-l ECDH-ECDSA-AES128-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.1 ECDH-ECDSA-AES128 +-G +-v 2 +-l ECDH-ECDSA-AES128-SHA +-A ./certs/server-ecc.pem + +# server DTLSv1.1 ECDH-ECDSA-AES256 +-G +-v 2 +-l ECDH-ECDSA-AES256-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.1 ECDH-ECDSA-AES256 +-G +-v 2 +-l ECDH-ECDSA-AES256-SHA +-A ./certs/server-ecc.pem + +# server DTLSv1.2 ECDHE-ECDSA-RC4 +-G +-v 3 +-l ECDH-ECDSA-RC4-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDH-ECDSA-RC4 +-G +-v 3 +-l ECDH-ECDSA-RC4-SHA +-A ./certs/server-ecc.pem + +# server DTLSv1.2 ECDH-ECDSA-DES3 +-G +-v 3 +-l ECDH-ECDSA-DES-CBC3-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDH-ECDSA-DES3 +-G +-v 3 +-l ECDH-ECDSA-DES-CBC3-SHA +-A ./certs/server-ecc.pem + +# server DTLSv1.2 ECDH-ECDSA-AES128 +-G +-v 3 +-l ECDH-ECDSA-AES128-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDH-ECDSA-AES128 +-G +-v 3 +-l ECDH-ECDSA-AES128-SHA +-A ./certs/server-ecc.pem + +# server DTLSv1.2 ECDH-ECDSA-AES128-SHA256 +-G +-v 3 +-l ECDH-ECDSA-AES128-SHA256 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDH-ECDSA-AES128-SHA256 +-G +-v 3 +-l ECDH-ECDSA-AES128-SHA256 +-A ./certs/server-ecc.pem + +# server DTLSv1.2 ECDH-ECDSA-AES256 +-G +-v 3 +-l ECDH-ECDSA-AES256-SHA +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDH-ECDSA-AES256 +-G +-v 3 +-l ECDH-ECDSA-AES256-SHA +-A ./certs/server-ecc.pem + +# server DTLSv1.2 ECDHE-RSA-AES256-SHA384 +-G +-v 3 +-l ECDHE-RSA-AES256-SHA384 + +# client DTLSv1.2 ECDHE-RSA-AES256-SHA384 +-G +-v 3 +-l ECDHE-RSA-AES256-SHA384 + +# server DTLSv1.2 ECDHE-ECDSA-AES256-SHA384 +-G +-v 3 +-l ECDHE-ECDSA-AES256-SHA384 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDHE-ECDSA-AES256-SHA384 +-G +-v 3 +-l ECDHE-ECDSA-AES256-SHA384 +-A ./certs/server-ecc.pem + +# server DTLSv1.2 ECDH-RSA-AES256-SHA384 +-G +-v 3 +-l ECDH-RSA-AES256-SHA384 +-c ./certs/server-ecc-rsa.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDH-RSA-AES256-SHA384 +-G +-v 3 +-l ECDH-RSA-AES256-SHA384 + +# server DTLSv1.2 ECDH-ECDSA-AES256-SHA384 +-G +-v 3 +-l ECDH-ECDSA-AES256-SHA384 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDH-ECDSA-AES256-SHA384 +-G +-v 3 +-l ECDH-ECDSA-AES256-SHA384 +-A ./certs/server-ecc.pem + +# server TLSv1 ECDHE-PSK-AES128-SHA256 +-s +-G +-v 1 +-l ECDHE-PSK-AES128-SHA256 + +# client TLSv1 ECDHE-PSK-AES128-SHA256 +-s +-G +-v 1 +-l ECDHE-PSK-AES128-SHA256 + +# server TLSv1.1 ECDHE-PSK-AES128-SHA256 +-s +-G +-v 2 +-l ECDHE-PSK-AES128-SHA256 + +# client TLSv1.1 ECDHE-PSK-AES128-SHA256 +-s +-G +-v 2 +-l ECDHE-PSK-AES128-SHA256 + +# server TLSv1.2 ECDHE-PSK-AES128-SHA256 +-s +-G +-v 3 +-l ECDHE-PSK-AES128-SHA256 + +# client TLSv1.2 ECDHE-PSK-AES128-SHA256 +-s +-G +-v 3 +-l ECDHE-PSK-AES128-SHA256 + +# server TLSv1 ECDHE-PSK-NULL-SHA256 +-s +-G +-v 1 +-l ECDHE-PSK-NULL-SHA256 + +# client TLSv1 ECDHE-PSK-NULL-SHA256 +-s +-G +-v 1 +-l ECDHE-PSK-NULL-SHA256 + +# server TLSv1.1 ECDHE-PSK-NULL-SHA256 +-s +-G +-v 2 +-l ECDHE-PSK-NULL-SHA256 + +# client TLSv1.1 ECDHE-PSK-NULL-SHA256 +-s +-G +-v 2 +-l ECDHE-PSK-NULL-SHA256 + +# server TLSv1.2 ECDHE-PSK-NULL-SHA256 +-s +-G +-v 3 +-l ECDHE-PSK-NULL-SHA256 + +# client TLSv1.2 ECDHE-PSK-NULL-SHA256 +-s +-G +-v 3 +-l ECDHE-PSK-NULL-SHA256 + +# server DTLSv1 PSK-AES128 +-s +-G +-v 2 +-l PSK-AES128-CBC-SHA + +# client DTLSv1 PSK-AES128 +-s +-G +-v 2 +-l PSK-AES128-CBC-SHA + +# server DTLSv1 PSK-AES256 +-s +-G +-v 2 +-l PSK-AES256-CBC-SHA + +# client DTLSv1 PSK-AES256 +-s +-G +-v 2 +-l PSK-AES256-CBC-SHA + +# server DTLSv1.2 PSK-AES128 +-s +-G +-v 3 +-l PSK-AES128-CBC-SHA + +# client DTLSv1.2 PSK-AES128 +-s +-G +-v 3 +-l PSK-AES128-CBC-SHA + +# server DTLSv1.2 PSK-AES256 +-s +-G +-v 3 +-l PSK-AES256-CBC-SHA + +# client DTLSv1.2 PSK-AES256 +-s +-G +-v 3 +-l PSK-AES256-CBC-SHA + +# server DTLSv1.2 PSK-AES128-SHA256 +-s +-G +-v 3 +-l PSK-AES128-CBC-SHA256 + +# client DTLSv1.2 PSK-AES128-SHA256 +-s +-G +-v 3 +-l PSK-AES128-CBC-SHA256 + +# server DTLSv1.2 PSK-AES256-SHA384 +-s +-G +-v 3 +-l PSK-AES256-CBC-SHA384 + +# client DTLSv1.2 PSK-AES256-SHA384 +-s +-G +-v 3 +-l PSK-AES256-CBC-SHA384 + +# server DTLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 +-G +-v 3 +-l ECDHE-ECDSA-AES128-GCM-SHA256 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 +-G +-v 3 +-l ECDHE-ECDSA-AES128-GCM-SHA256 +-A ./certs/server-ecc.pem + +# server DTLSv1.2 ECDHE-ECDSA-AES256-GCM-SHA384 +-G +-v 3 +-l ECDHE-ECDSA-AES256-GCM-SHA384 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDHE-ECDSA-AES256-GCM-SHA384 +-G +-v 3 +-l ECDHE-ECDSA-AES256-GCM-SHA384 +-A ./certs/server-ecc.pem + +# server DTLSv1.2 ECDH-ECDSA-AES128-GCM-SHA256 +-G +-v 3 +-l ECDH-ECDSA-AES128-GCM-SHA256 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDH-ECDSA-AES128-GCM-SHA256 +-G +-v 3 +-l ECDH-ECDSA-AES128-GCM-SHA256 +-A ./certs/server-ecc.pem + +# server DTLSv1.2 ECDH-ECDSA-AES256-GCM-SHA384 +-G +-v 3 +-l ECDH-ECDSA-AES256-GCM-SHA384 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDH-ECDSA-AES256-GCM-SHA384 +-G +-v 3 +-l ECDH-ECDSA-AES256-GCM-SHA384 +-A ./certs/server-ecc.pem + +# server DTLSv1.2 ECDHE-RSA-AES128-GCM-SHA256 +-G +-v 3 +-l ECDHE-RSA-AES128-GCM-SHA256 + +# client DTLSv1.2 ECDHE-RSA-AES128-GCM-SHA256 +-G +-v 3 +-l ECDHE-RSA-AES128-GCM-SHA256 + +# server DTLSv1.2 ECDHE-RSA-AES256-GCM-SHA384 +-G +-v 3 +-l ECDHE-RSA-AES256-GCM-SHA384 + +# client DTLSv1.2 ECDHE-RSA-AES256-GCM-SHA384 +-G +-v 3 +-l ECDHE-RSA-AES256-GCM-SHA384 + +# server DTLSv1.2 ECDH-RSA-AES128-GCM-SHA256 +-G +-v 3 +-l ECDH-RSA-AES128-GCM-SHA256 +-c ./certs/server-ecc-rsa.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDH-RSA-AES128-GCM-SHA256 +-G +-v 3 +-l ECDH-RSA-AES128-GCM-SHA256 + +# server DTLSv1.2 ECDH-RSA-AES256-GCM-SHA384 +-G +-v 3 +-l ECDH-RSA-AES256-GCM-SHA384 +-c ./certs/server-ecc-rsa.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDH-RSA-AES256-GCM-SHA384 +-G +-v 3 +-l ECDH-RSA-AES256-GCM-SHA384 + +# server DTLSv1.2 PSK-AES128-GCM-SHA256 +-G +-s +-v 3 +-l PSK-AES128-GCM-SHA256 + +# client DTLSv1.2 PSK-AES128-GCM-SHA256 +-G +-s +-v 3 +-l PSK-AES128-GCM-SHA256 + +# server DTLSv1.2 PSK-AES256-GCM-SHA384 +-G +-s +-v 3 +-l PSK-AES256-GCM-SHA384 + +# client DTLSv1.2 PSK-AES256-GCM-SHA384 +-G +-s +-v 3 +-l PSK-AES256-GCM-SHA384 + +# server DTLSv1.2 ECDHE-ECDSA-AES128-CCM +-G +-v 3 +-l ECDHE-ECDSA-AES128-CCM +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDHE-ECDSA-AES128-CCM +-G +-v 3 +-l ECDHE-ECDSA-AES128-CCM +-A ./certs/server-ecc.pem + +# server DTLSv1.2 ECDHE-ECDSA-AES128-CCM-8 +-G +-v 3 +-l ECDHE-ECDSA-AES128-CCM-8 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDHE-ECDSA-AES128-CCM-8 +-G +-v 3 +-l ECDHE-ECDSA-AES128-CCM-8 +-A ./certs/server-ecc.pem + +# server DTLSv1.2 ECDHE-ECDSA-AES256-CCM-8 +-G +-v 3 +-l ECDHE-ECDSA-AES256-CCM-8 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDHE-ECDSA-AES256-CCM-8 +-G +-v 3 +-l ECDHE-ECDSA-AES256-CCM-8 +-A ./certs/server-ecc.pem + +# server DTLSv1.2 ADH-AES128-SHA +-G +-a +-v 3 +-l ADH-AES128-SHA + +# client DTLSv1.2 ADH-AES128-SHA +-G +-a +-v 3 +-l ADH-AES128-SHA + +# server DTLSv1.0 ADH-AES128-SHA +-G +-a +-v 2 +-l ADH-AES128-SHA + +# client DTLSv1.0 ADH-AES128-SHA +-G +-a +-v 2 +-l ADH-AES128-SHA + diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 9ff1241dd..c79dcdf0f 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -1936,6 +1936,10 @@ struct WOLFSSL_CTX { byte quietShutdown; /* don't send close notify */ byte groupMessages; /* group handshake messages before sending */ byte minDowngrade; /* minimum downgrade version */ +#if defined(WOLFSSL_SCTP) && defined(WOLFSSL_DTLS) + byte dtlsSctp; /* DTLS-over-SCTP mode */ + word16 dtlsMtuSz; /* DTLS MTU size */ +#endif #ifndef NO_DH word16 minDhKeySz; /* minimum DH key size */ #endif @@ -2401,6 +2405,9 @@ typedef struct Options { #endif #ifdef WOLFSSL_DTLS word16 dtlsHsRetain:1; /* DTLS retaining HS data */ +#ifdef WOLFSSL_SCTP + word16 dtlsSctp:1; /* DTLS-over-SCTP mode */ +#endif #endif /* need full byte values for this section */ @@ -2740,6 +2747,9 @@ struct WOLFSSL { void* IOCB_CookieCtx; /* gen cookie ctx */ word32 dtls_expected_rx; wc_dtls_export dtls_export; /* export function for session */ +#ifdef WOLFSSL_SCTP + word16 dtlsMtuSz; +#endif /* WOLFSSL_SCTP */ #endif #ifdef WOLFSSL_CALLBACKS HandShakeInfo handShakeInfo; /* info saved during handshake */ diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index 2af2dfffa..4f234b058 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -409,6 +409,11 @@ WOLFSSL_API int wolfSSL_dtls(WOLFSSL* ssl); WOLFSSL_API int wolfSSL_dtls_set_peer(WOLFSSL*, void*, unsigned int); WOLFSSL_API int wolfSSL_dtls_get_peer(WOLFSSL*, void*, unsigned int*); +WOLFSSL_API int wolfSSL_CTX_dtls_set_sctp(WOLFSSL_CTX*); +WOLFSSL_API int wolfSSL_dtls_set_sctp(WOLFSSL*); +WOLFSSL_API int wolfSSL_CTX_dtls_set_mtu(WOLFSSL_CTX*, unsigned short); +WOLFSSL_API int wolfSSL_dtls_set_mtu(WOLFSSL*, unsigned short); + WOLFSSL_API int wolfSSL_ERR_GET_REASON(unsigned long err); WOLFSSL_API char* wolfSSL_ERR_error_string(unsigned long,char*); WOLFSSL_API void wolfSSL_ERR_error_string_n(unsigned long e, char* buf, diff --git a/wolfssl/test.h b/wolfssl/test.h index f23748ee4..51be479e3 100644 --- a/wolfssl/test.h +++ b/wolfssl/test.h @@ -564,11 +564,12 @@ static INLINE void showPeer(WOLFSSL* ssl) static INLINE void build_addr(SOCKADDR_IN_T* addr, const char* peer, - word16 port, int udp) + word16 port, int udp, int sctp) { int useLookup = 0; (void)useLookup; (void)udp; + (void)sctp; if (addr == NULL) err_sys("invalid argument to build_addr, addr is NULL"); @@ -628,8 +629,17 @@ static INLINE void build_addr(SOCKADDR_IN_T* addr, const char* peer, memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_INET_V; - hints.ai_socktype = udp ? SOCK_DGRAM : SOCK_STREAM; - hints.ai_protocol = udp ? IPPROTO_UDP : IPPROTO_TCP; + if (udp) { + hints.ai_socktype = SOCK_DGRAM; + hints.ai_protocol = IPPROTO_UDP; + } else if (sctp) { + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_SCTP; + } + else { + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + } SNPRINTF(strPort, sizeof(strPort), "%d", port); strPort[79] = '\0'; @@ -649,12 +659,14 @@ static INLINE void build_addr(SOCKADDR_IN_T* addr, const char* peer, } -static INLINE void tcp_socket(SOCKET_T* sockfd, int udp) +static INLINE void tcp_socket(SOCKET_T* sockfd, int udp, int sctp) { if (udp) - *sockfd = socket(AF_INET_V, SOCK_DGRAM, 0); + *sockfd = socket(AF_INET_V, SOCK_DGRAM, IPPROTO_UDP); + else if (sctp) + *sockfd = socket(AF_INET_V, SOCK_STREAM, IPPROTO_SCTP); else - *sockfd = socket(AF_INET_V, SOCK_STREAM, 0); + *sockfd = socket(AF_INET_V, SOCK_STREAM, IPPROTO_TCP); if(WOLFSSL_SOCKET_IS_INVALID(*sockfd)) { err_sys("socket failed\n"); @@ -677,7 +689,7 @@ static INLINE void tcp_socket(SOCKET_T* sockfd, int udp) #endif /* S_NOSIGPIPE */ #if defined(TCP_NODELAY) - if (!udp) + if (!udp && !sctp) { int on = 1; socklen_t len = sizeof(on); @@ -690,14 +702,14 @@ static INLINE void tcp_socket(SOCKET_T* sockfd, int udp) } static INLINE void tcp_connect(SOCKET_T* sockfd, const char* ip, word16 port, - int udp, WOLFSSL* ssl) + int udp, int sctp, WOLFSSL* ssl) { SOCKADDR_IN_T addr; - build_addr(&addr, ip, port, udp); - if(udp) { + build_addr(&addr, ip, port, udp, sctp); + if (udp) { wolfSSL_dtls_set_peer(ssl, &addr, sizeof(addr)); } - tcp_socket(sockfd, udp); + tcp_socket(sockfd, udp, sctp); if (!udp) { if (connect(*sockfd, (const struct sockaddr*)&addr, sizeof(addr)) != 0) @@ -757,14 +769,14 @@ static INLINE int tcp_select(SOCKET_T socketfd, int to_sec) static INLINE void tcp_listen(SOCKET_T* sockfd, word16* port, int useAnyAddr, - int udp) + int udp, int sctp) { SOCKADDR_IN_T addr; /* don't use INADDR_ANY by default, firewall may block, make user switch on */ - build_addr(&addr, (useAnyAddr ? INADDR_ANY : wolfSSLIP), *port, udp); - tcp_socket(sockfd, udp); + build_addr(&addr, (useAnyAddr ? INADDR_ANY : wolfSSLIP), *port, udp, sctp); + tcp_socket(sockfd, udp, sctp); #if !defined(USE_WINDOWS_API) && !defined(WOLFSSL_MDK_ARM)\ && !defined(WOLFSSL_KEIL_TCP_NET) @@ -826,8 +838,8 @@ static INLINE void udp_accept(SOCKET_T* sockfd, SOCKET_T* clientfd, SOCKADDR_IN_T addr; (void)args; - build_addr(&addr, (useAnyAddr ? INADDR_ANY : wolfSSLIP), port, 1); - tcp_socket(sockfd, 1); + build_addr(&addr, (useAnyAddr ? INADDR_ANY : wolfSSLIP), port, 1, 0); + tcp_socket(sockfd, 1, 0); #if !defined(USE_WINDOWS_API) && !defined(WOLFSSL_MDK_ARM) \ @@ -879,7 +891,7 @@ static INLINE void udp_accept(SOCKET_T* sockfd, SOCKET_T* clientfd, static INLINE void tcp_accept(SOCKET_T* sockfd, SOCKET_T* clientfd, func_args* args, word16 port, int useAnyAddr, - int udp, int ready_file, int do_listen) + int udp, int sctp, int ready_file, int do_listen) { SOCKADDR_IN_T client; socklen_t client_len = sizeof(client); @@ -893,7 +905,7 @@ static INLINE void tcp_accept(SOCKET_T* sockfd, SOCKET_T* clientfd, } if(do_listen) { - tcp_listen(sockfd, &port, useAnyAddr, udp); + tcp_listen(sockfd, &port, useAnyAddr, udp, sctp); #if defined(_POSIX_THREADS) && defined(NO_MAIN_DRIVER) && !defined(__MINGW32__) /* signal ready to tcp_accept */