Merge pull request #536 from ejohnstown/dtls-sctp

DTLS over SCTP
This commit is contained in:
toddouska
2016-08-30 13:09:40 -07:00
committed by GitHub
21 changed files with 1867 additions and 122 deletions

4
.gitignore vendored
View File

@@ -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

View File

@@ -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 <sys/socket.h>
#include <arpa/inet.h>
]],
[[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"

View File

@@ -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");
}

View File

@@ -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 */

View File

@@ -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)

View File

@@ -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
}

View File

@@ -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

38
examples/sctp/include.am Normal file
View File

@@ -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

View File

@@ -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 <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netinet/in.h>
/* std */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
/* wolfssl */
#include <wolfssl/options.h>
#include <wolfssl/ssl.h>
#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;
}

View File

@@ -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 <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netinet/in.h>
/* std */
#include <stdio.h>
#include <string.h>
#include <unistd.h>
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;
}

View File

@@ -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 <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
/* std */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
/* wolfssl */
#include <wolfssl/options.h>
#include <wolfssl/ssl.h>
#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;
}

View File

@@ -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 <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
/* std */
#include <stdio.h>
#include <string.h>
#include <unistd.h>
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;
}

View File

@@ -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 */

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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));

View File

@@ -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 */

1111
tests/test-sctp.conf Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -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 */

View File

@@ -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,

View File

@@ -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 */