examples: client/server: support DTLSv1.3 (-u -v4)

This commits add some new options to examples/[server,client] to support testing
of DTLS v1.3.

client: add waitTicket option

If this option is used, the client will wait until it receives a sessionTicket
from the server. This is useful when testing DTLS retransmission.

client: add waitKeyUpdate option

When this option is set, the client waits until the UpdateKey message is
acknowledged by the server. This is useful to test DTLS retransmission logic
This commit is contained in:
Marco Oliverio
2022-05-20 10:00:24 +02:00
committed by David Garske
parent c1dc90d9b0
commit 4e112419f5
3 changed files with 190 additions and 7 deletions

View File

@@ -142,6 +142,10 @@ static int lng_index = 0;
#endif
#ifdef HAVE_SESSION_TICKET
#ifndef SESSION_TICKET_LEN
#define SESSION_TICKET_LEN 256
#endif
static int sessionTicketCB(WOLFSSL* ssl,
const unsigned char* ticket, int ticketSz,
void* ctx)
@@ -1868,6 +1872,12 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
#ifdef WOLFSSL_SRTP
{ "srtp", 2, 260 }, /* optional argument */
#endif
#ifdef WOLFSSL_DTLS13
/* allow waitTicket option even when HAVE_SESSION_TICKET is 0. Otherwise
* tests that use this option will ignore the options following
* --waitTicket in the command line and fail */
{"waitTicket", 0, 261},
#endif /* WOLFSSL_DTLS13 */
{ 0, 0, 0 }
};
#endif
@@ -1994,6 +2004,10 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
const char* dtlsSrtpProfiles = NULL;
#endif
#ifdef HAVE_SESSION_TICKET
int waitTicket = 0;
#endif /* HAVE_SESSION_TICKET */
char buffer[WOLFSSL_MAX_ERROR_SZ];
int argc = ((func_args*)args)->argc;
@@ -2141,6 +2155,14 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
break;
#endif
#ifdef WOLFSSL_DTLS13
case 261:
#ifdef HAVE_SESSION_TICKET
waitTicket = 1;
#endif /* HAVE_SESSION_TICKET */
break;
#endif /* WOLFSSL_DTLS13 */
case 'G' :
#ifdef WOLFSSL_SCTP
doDTLS = 1;
@@ -2749,12 +2771,21 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
}
else {
if (doDTLS) {
if (version == 3)
if (version == 3) {
version = -2;
}
#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE)
else if (version == EITHER_DOWNGRADE_VERSION)
else if (version == EITHER_DOWNGRADE_VERSION) {
version = -3;
}
#endif
else if (version == 4) {
#ifdef WOLFSSL_DTLS13
version = -4;
#else
err_sys("Bad DTLS version");
#endif /* WOLFSSL_DTLS13 */
}
else
version = -1;
}
@@ -2833,6 +2864,11 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
method = wolfDTLSv1_2_client_method_ex;
break;
#endif
#ifdef WOLFSSL_DTLS13
case -4:
method = wolfDTLSv1_3_client_method_ex;
break;
#endif /* WOLFSSL_DTLS13 */
#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE)
case -3:
method = wolfDTLSv1_2_method_ex;
@@ -3450,7 +3486,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
#endif
#if defined(WOLFSSL_TLS13) && defined(HAVE_SUPPORTED_CURVES)
if (!helloRetry && version >= 4) {
if (!helloRetry && (version >= 4 || version <= -4)) {
SetKeyShare(ssl, onlyKeyShare, useX25519, useX448, usePqc,
pqcAlg, 0);
}
@@ -4029,6 +4065,29 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
(void)ClientWrite(ssl, msg, msgSz, "", 0);
#endif
#if defined(HAVE_SESSION_TICKET)
while (waitTicket == 1) {
unsigned char ticketBuf[SESSION_TICKET_LEN];
int zeroReturn = 0;
word32 size;
(void)zeroReturn;
size = sizeof(ticketBuf);
err = wolfSSL_get_SessionTicket(ssl, ticketBuf, &size);
if (err < 0)
err_sys("wolfSSL_get_SessionTicket failed");
if (size == 0) {
err = process_handshake_messages(ssl, !nonBlocking, &zeroReturn);
if (err < 0)
err_sys("error waiting for session ticket ");
}
else {
waitTicket = 0;
}
}
#endif
#ifndef NO_SESSION_CACHE
if (resumeSession) {
session = wolfSSL_get1_session(ssl);

View File

@@ -546,6 +546,11 @@ static void ServerRead(WOLFSSL* ssl, char* input, int inputLen)
}
else if (SSL_get_error(ssl, 0) == 0 &&
tcp_select(SSL_get_fd(ssl), 0) == TEST_RECV_READY) {
err = wolfSSL_peek(ssl, buffer, 0);
if(err < 0) {
err_sys_ex(runWithErrors, "wolfSSL_peek failed");
}
if (wolfSSL_pending(ssl))
err = WOLFSSL_ERROR_WANT_READ;
}
} while (err == WC_PENDING_E || err == WOLFSSL_ERROR_WANT_READ);
@@ -2160,13 +2165,22 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args)
}
else {
if (doDTLS) {
if (version == 3)
if (version == 3) {
version = -2;
}
else if (version == 4) {
#ifdef WOLFSSL_DTLS13
version = -4;
#else
err_sys_ex(runWithErrors, "Bad DTLS version");
#endif /* WOLFSSL_DTLS13 */
}
#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE)
else if (version == EITHER_DOWNGRADE_VERSION)
else if (version == EITHER_DOWNGRADE_VERSION) {
version = -3;
}
#endif
else
else if (version == 2)
version = -1;
}
}
@@ -2225,7 +2239,16 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args)
#endif
case SERVER_DOWNGRADE_VERSION:
method = wolfSSLv23_server_method_ex;
if (!doDTLS) {
method = wolfSSLv23_server_method_ex;
}
else {
#ifdef WOLFSSL_DTLS13
method = wolfDTLS_server_method_ex;
#else
err_sys_ex(runWithErrors, "version not supported");
#endif /* WOLFSSL_DTLS13 */
}
break;
#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE)
case EITHER_DOWNGRADE_VERSION:
@@ -2246,6 +2269,11 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args)
method = wolfDTLSv1_2_server_method_ex;
break;
#endif
#ifdef WOLFSSL_DTLS13
case -4:
method = wolfDTLSv1_3_server_method_ex;
break;
#endif
#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE)
case -3:
method = wolfDTLSv1_2_method_ex;
@@ -2291,6 +2319,19 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args)
err_sys_ex(catastrophic, "unable to get ctx");
if (minVersion != SERVER_INVALID_VERSION) {
#ifdef WOLFSSL_DTLS13
switch (minVersion) {
case 4:
minVersion = WOLFSSL_DTLSV1_3;
break;
case 3:
minVersion = WOLFSSL_DTLSV1_2;
break;
case 2:
minVersion = WOLFSSL_DTLSV1;
break;
}
#endif /* WOLFSSL_DTLS13 */
wolfSSL_CTX_SetMinVersion(ctx, minVersion);
}
@@ -3343,6 +3384,7 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args)
WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT), 0);
wolfSSL_request_certificate(ssl);
}
#endif
@@ -3395,6 +3437,23 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args)
Task_yield();
#endif
#if defined(WOLFSSL_DTLS13)
if (wolfSSL_dtls(ssl) && version == -4) {
int zero_return = 0;
while (wolfSSL_dtls13_has_pending_msg(ssl)) {
err =
process_handshake_messages(ssl, !nonBlocking, &zero_return);
if (err < 0) {
/* other peer closes the connection, non fatal */
if (zero_return)
break;
err_sys("Error while processing pending DTLSv1.3 messages");
}
}
}
#endif /* WOLFSSL_DTLS13 */
ret = SSL_shutdown(ssl);
if (wc_shutdown && ret == WOLFSSL_SHUTDOWN_NOT_DONE) {
while (tcp_select(wolfSSL_get_fd(ssl), DEFAULT_TIMEOUT_SEC) ==

View File

@@ -350,6 +350,10 @@
#endif
#endif
#ifndef DEFAULT_TIMEOUT_SEC
#define DEFAULT_TIMEOUT_SEC 2
#endif
/* all certs relative to wolfSSL home directory now */
#if defined(WOLFSSL_NO_CURRDIR) || defined(WOLFSSL_MDK_SHELL)
#define caCertFile "certs/ca-cert.pem"
@@ -5299,6 +5303,67 @@ static WC_INLINE void EarlyDataStatus(WOLFSSL* ssl)
}
#endif /* WOLFSSL_EARLY_DATA */
#if defined(HAVE_SESSION_TICKET) || defined (WOLFSSL_DTLS13)
static WC_INLINE int process_handshake_messages(WOLFSSL* ssl, int blocking,
int* zero_return)
{
int timeout = DEFAULT_TIMEOUT_SEC;
char foo[1];
int ret = 0;
int dtls;
(void)dtls;
if (zero_return == NULL || ssl == NULL)
return -1;
dtls = wolfSSL_dtls(ssl);
*zero_return = 0;
if (!blocking) {
#ifdef WOLFSSL_DTLS
if (dtls) {
timeout = wolfSSL_dtls_get_current_timeout(ssl);
#ifdef WOLFSSL_DTLS13
if (timeout > 4 && wolfSSL_dtls13_use_quick_timeout(ssl))
timeout /= 4;
#endif /* WOLFSSL_DTLS13 */
}
#endif /* WOLFSSL_DTLS */
ret = tcp_select(wolfSSL_get_fd(ssl), timeout);
if (ret == TEST_ERROR_READY) {
err_sys("tcp_select error");
return -1;
}
if (ret == TEST_TIMEOUT) {
#ifdef WOLFSSL_DTLS
if (dtls) {
ret = wolfSSL_dtls_got_timeout(ssl);
if (ret != WOLFSSL_SUCCESS && !wolfSSL_want_write(ssl) &&
!wolfSSL_want_read(ssl)) {
err_sys("got timeout error");
return -1;
}
}
#endif /* WOLFSSL_DTLS */
/* do the peek to detect if the peer closed the connection*/
}
}
ret = wolfSSL_peek(ssl, foo, 0);
if (ret < 0 && !wolfSSL_want_read(ssl) && !wolfSSL_want_write(ssl)) {
ret = wolfSSL_get_error(ssl, ret);
if (ret == WOLFSSL_ERROR_ZERO_RETURN)
*zero_return = 1;
return -1;
}
return 0;
}
#endif /* HAVE_SESSION_TICKET || WOLFSSL_DTLS13 */
#if !defined(NO_FILESYSTEM) && defined(OPENSSL_EXTRA) && \
defined(DEBUG_UNIT_TEST_CERTS)