Files
wolfssl/tests/api/test_dtls.c
Juliusz Sosinowicz 429b690370 Address code review
2026-01-19 09:38:17 +01:00

2570 lines
100 KiB
C

/* test_dtls.c
*
* Copyright (C) 2006-2025 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 3 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
*/
#include <tests/unit.h>
#ifdef NO_INLINE
#include <wolfssl/wolfcrypt/misc.h>
#else
#define WOLFSSL_MISC_INCLUDED
#include <wolfcrypt/src/misc.c>
#endif
#include <wolfssl/ssl.h>
#include <wolfssl/internal.h>
#include <tests/utils.h>
#include <tests/api/test_dtls.h>
int test_dtls12_basic_connection_id(void)
{
EXPECT_DECLS;
#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_DTLS_CID)
unsigned char client_cid[] = { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
unsigned char server_cid[] = { 0, 1, 2, 3, 4, 5 };
unsigned char readBuf[40];
void * cid = NULL;
const char* params[] = {
#ifndef NO_RSA
#ifndef NO_SHA256
#if defined(WOLFSSL_AES_128) && defined(WOLFSSL_STATIC_RSA)
"AES128-SHA256",
#ifdef HAVE_AESCCM
"AES128-CCM8",
#endif
#endif /* WOLFSSL_AES_128 && WOLFSSL_STATIC_RSA */
#if defined(WOLFSSL_AES_128)
"DHE-RSA-AES128-SHA256",
"ECDHE-RSA-AES128-SHA256",
#ifdef HAVE_AESGCM
"DHE-RSA-AES128-GCM-SHA256",
"ECDHE-RSA-AES128-GCM-SHA256",
#endif
#endif /* WOLFSSL_AES_128 */
#endif /* NO_SHA256 */
#endif /* NO_RSA */
#if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) && !defined(HAVE_FIPS)
"DHE-RSA-CHACHA20-POLY1305",
"DHE-RSA-CHACHA20-POLY1305-OLD",
"ECDHE-RSA-CHACHA20-POLY1305",
"ECDHE-RSA-CHACHA20-POLY1305-OLD",
#endif
#ifndef NO_PSK
"DHE-PSK-AES128-CBC-SHA256",
#ifdef WOLFSSL_AES_256
"DHE-PSK-AES256-GCM-SHA384",
#endif
#ifdef HAVE_NULL_CIPHER
"DHE-PSK-NULL-SHA256",
#endif
"DHE-PSK-AES128-CCM",
#endif
};
size_t i;
struct {
byte drop:1;
byte changeCID:1;
} run_params[] = {
{ .drop = 0, .changeCID = 0 },
{ .drop = 1, .changeCID = 0 },
{ .drop = 0, .changeCID = 1 },
};
/* We check if the side included the CID in their output */
#define CLIENT_CID() mymemmem(test_ctx.s_buff, test_ctx.s_len, \
client_cid, sizeof(client_cid))
#define SERVER_CID() mymemmem(test_ctx.c_buff, test_ctx.c_len, \
server_cid, sizeof(server_cid))
#define RESET_CID(cid) if ((cid) != NULL) { \
((char*)(cid))[0] = -1; \
}
printf("\n");
for (i = 0; i < XELEM_CNT(params) && EXPECT_SUCCESS(); i++) {
size_t j;
for (j = 0; j < XELEM_CNT(run_params); j++) {
WOLFSSL_CTX *ctx_c = NULL, *ctx_s = NULL;
WOLFSSL *ssl_c = NULL, *ssl_s = NULL;
struct test_memio_ctx test_ctx;
printf("Testing %s run #%ld ... ", params[i], (long int)j);
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c,
&ssl_s, wolfDTLSv1_2_client_method, wolfDTLSv1_2_server_method),
0);
ExpectIntEQ(wolfSSL_set_cipher_list(ssl_c, params[i]), 1);
ExpectIntEQ(wolfSSL_set_cipher_list(ssl_s, params[i]), 1);
ExpectIntEQ(wolfSSL_dtls_cid_use(ssl_c), 1);
ExpectIntEQ(wolfSSL_dtls_cid_set(ssl_c, server_cid,
sizeof(server_cid)), 1);
ExpectIntEQ(wolfSSL_dtls_cid_use(ssl_s), 1);
ExpectIntEQ(wolfSSL_dtls_cid_set(ssl_s, client_cid,
sizeof(client_cid)), 1);
#ifndef NO_PSK
if (XSTRSTR(params[i], "-PSK-") != NULL) {
wolfSSL_set_psk_client_callback(ssl_c, my_psk_client_cb);
wolfSSL_set_psk_server_callback(ssl_s, my_psk_server_cb);
}
#endif
#ifdef HAVE_SECURE_RENEGOTIATION
ExpectIntEQ(wolfSSL_UseSecureRenegotiation(ssl_c), 1);
ExpectIntEQ(wolfSSL_UseSecureRenegotiation(ssl_s), 1);
#endif
/* CH1 */
wolfSSL_SetLoggingPrefix("client");
ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
ExpectNull(CLIENT_CID());
if (run_params[j].drop) {
test_memio_clear_buffer(&test_ctx, 0);
test_memio_clear_buffer(&test_ctx, 1);
ExpectIntEQ(wolfSSL_dtls_got_timeout(ssl_c), 1);
ExpectNull(CLIENT_CID());
}
/* HVR */
wolfSSL_SetLoggingPrefix("server");
ExpectIntEQ(wolfSSL_negotiate(ssl_s), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ);
ExpectNull(SERVER_CID());
/* No point dropping HVR */
/* CH2 */
wolfSSL_SetLoggingPrefix("client");
ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
ExpectNull(CLIENT_CID());
if (run_params[j].drop) {
test_memio_clear_buffer(&test_ctx, 0);
test_memio_clear_buffer(&test_ctx, 1);
ExpectIntEQ(wolfSSL_dtls_got_timeout(ssl_c), 1);
ExpectNull(CLIENT_CID());
}
/* Server first flight */
wolfSSL_SetLoggingPrefix("server");
ExpectIntEQ(wolfSSL_negotiate(ssl_s), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ);
ExpectNull(SERVER_CID());
if (run_params[j].drop) {
test_memio_clear_buffer(&test_ctx, 0);
test_memio_clear_buffer(&test_ctx, 1);
ExpectIntEQ(wolfSSL_dtls_got_timeout(ssl_s), 1);
ExpectNull(SERVER_CID());
}
/* Client second flight */
wolfSSL_SetLoggingPrefix("client");
ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
ExpectNotNull(CLIENT_CID());
if (run_params[j].drop) {
test_memio_clear_buffer(&test_ctx, 0);
test_memio_clear_buffer(&test_ctx, 1);
ExpectIntEQ(wolfSSL_dtls_got_timeout(ssl_c), 1);
ExpectNotNull(CLIENT_CID());
}
/* Server second flight */
wolfSSL_SetLoggingPrefix("server");
ExpectIntEQ(wolfSSL_negotiate(ssl_s), 1);
ExpectNotNull(SERVER_CID());
if (run_params[j].drop) {
test_memio_clear_buffer(&test_ctx, 0);
test_memio_clear_buffer(&test_ctx, 1);
ExpectIntEQ(wolfSSL_dtls_got_timeout(ssl_s), 1);
ExpectNotNull(SERVER_CID());
}
/* Client complete connection */
wolfSSL_SetLoggingPrefix("client");
ExpectIntEQ(wolfSSL_negotiate(ssl_c), 1);
ExpectNull(CLIENT_CID());
/* Write some data */
wolfSSL_SetLoggingPrefix("client");
ExpectIntEQ(wolfSSL_write(ssl_c, params[i],
(int)XSTRLEN(params[i])), XSTRLEN(params[i]));
ExpectNotNull(CLIENT_CID());
wolfSSL_SetLoggingPrefix("server");
ExpectIntEQ(wolfSSL_write(ssl_s, params[i],
(int)XSTRLEN(params[i])), XSTRLEN(params[i]));
ExpectNotNull(SERVER_CID());
/* Read the data */
wolfSSL_SetLoggingPrefix("client");
XMEMSET(readBuf, 0, sizeof(readBuf));
ExpectIntEQ(wolfSSL_read(ssl_c, readBuf, sizeof(readBuf)),
XSTRLEN(params[i]));
ExpectStrEQ(readBuf, params[i]);
XMEMSET(readBuf, 0, sizeof(readBuf));
wolfSSL_SetLoggingPrefix("server");
ExpectIntEQ(wolfSSL_read(ssl_s, readBuf, sizeof(readBuf)),
XSTRLEN(params[i]));
ExpectStrEQ(readBuf, params[i]);
/* Write short data */
wolfSSL_SetLoggingPrefix("client");
ExpectIntEQ(wolfSSL_write(ssl_c, params[i], 1), 1);
ExpectNotNull(CLIENT_CID());
wolfSSL_SetLoggingPrefix("server");
ExpectIntEQ(wolfSSL_write(ssl_s, params[i], 1), 1);
ExpectNotNull(SERVER_CID());
/* Read the short data */
XMEMSET(readBuf, 0, sizeof(readBuf));
wolfSSL_SetLoggingPrefix("client");
ExpectIntEQ(wolfSSL_read(ssl_c, readBuf, sizeof(readBuf)), 1);
ExpectIntEQ(readBuf[0], params[i][0]);
XMEMSET(readBuf, 0, sizeof(readBuf));
wolfSSL_SetLoggingPrefix("server");
ExpectIntEQ(wolfSSL_read(ssl_s, readBuf, sizeof(readBuf)), 1);
ExpectIntEQ(readBuf[0], params[i][0]);
/* Write some data but with wrong CID */
wolfSSL_SetLoggingPrefix("client");
ExpectIntEQ(wolfSSL_write(ssl_c, params[i],
(int)XSTRLEN(params[i])), XSTRLEN(params[i]));
/* Reset client cid. */
ExpectNotNull(cid = CLIENT_CID());
RESET_CID(cid);
wolfSSL_SetLoggingPrefix("server");
ExpectIntEQ(wolfSSL_write(ssl_s, params[i],
(int)XSTRLEN(params[i])), XSTRLEN(params[i]));
/* Reset server cid. */
ExpectNotNull(cid = SERVER_CID());
RESET_CID(cid);
/* Try to read the data but it shouldn't be there */
wolfSSL_SetLoggingPrefix("client");
ExpectIntEQ(wolfSSL_read(ssl_c, readBuf, sizeof(readBuf)), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
wolfSSL_SetLoggingPrefix("server");
ExpectIntEQ(wolfSSL_read(ssl_s, readBuf, sizeof(readBuf)), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ);
#ifdef HAVE_SECURE_RENEGOTIATION
/* do two SCR's */
wolfSSL_SetLoggingPrefix("client");
ExpectIntEQ(wolfSSL_Rehandshake(ssl_c), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
ExpectIntEQ(wolfSSL_read(ssl_s, readBuf, sizeof(readBuf)), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ);
ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0);
/* SCR's after the first one have extra internal logic */
wolfSSL_SetLoggingPrefix("client");
ExpectIntEQ(wolfSSL_Rehandshake(ssl_c), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
ExpectIntEQ(wolfSSL_read(ssl_s, readBuf, sizeof(readBuf)), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ);
ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0);
if (run_params[j].changeCID) {
ExpectIntEQ(wolfSSL_dtls_cid_set(ssl_c, client_cid,
sizeof(client_cid)), 0);
/* Forcefully change the CID */
ssl_c->dtlsCidInfo->rx->id[0] = -1;
/* We need to init the rehandshake from the client, otherwise
* we won't be able to test changing the CID. It would be
* rejected by the record CID matching code. */
wolfSSL_SetLoggingPrefix("client");
ExpectIntEQ(wolfSSL_Rehandshake(ssl_c), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1),
WOLFSSL_ERROR_WANT_READ);
ExpectNotNull(CLIENT_CID());
ExpectIntEQ(wolfSSL_SSL_renegotiate_pending(ssl_c), 1);
/* Server first flight */
wolfSSL_SetLoggingPrefix("server");
ExpectIntEQ(wolfSSL_read(ssl_s, readBuf, sizeof(readBuf)), -1);
/* We expect the server to reject the CID change. */
ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), DTLS_CID_ERROR);
goto loop_exit;
}
/* Server init'd SCR */
/* Server request */
wolfSSL_SetLoggingPrefix("server");
ExpectIntEQ(wolfSSL_Rehandshake(ssl_s), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ);
ExpectNotNull(SERVER_CID());
ExpectIntEQ(wolfSSL_SSL_renegotiate_pending(ssl_s), 1);
if (run_params[j].drop) {
test_memio_clear_buffer(&test_ctx, 0);
test_memio_clear_buffer(&test_ctx, 1);
ExpectIntEQ(wolfSSL_dtls_got_timeout(ssl_s), 1);
ExpectNotNull(SERVER_CID());
}
/* Init SCR on client side with the server's request */
/* CH no HVR on SCR */
XMEMSET(readBuf, 0, sizeof(readBuf));
wolfSSL_SetLoggingPrefix("client");
ExpectIntEQ(wolfSSL_read(ssl_c, readBuf, sizeof(readBuf)), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
ExpectNotNull(CLIENT_CID());
ExpectIntEQ(wolfSSL_SSL_renegotiate_pending(ssl_c), 1);
if (run_params[j].drop) {
test_memio_clear_buffer(&test_ctx, 0);
test_memio_clear_buffer(&test_ctx, 1);
ExpectIntEQ(wolfSSL_dtls_got_timeout(ssl_c), 1);
ExpectNotNull(CLIENT_CID());
}
/* Server first flight */
wolfSSL_SetLoggingPrefix("server");
ExpectIntEQ(wolfSSL_negotiate(ssl_s), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ);
ExpectNotNull(SERVER_CID());
if (run_params[j].drop) {
test_memio_clear_buffer(&test_ctx, 0);
test_memio_clear_buffer(&test_ctx, 1);
ExpectIntEQ(wolfSSL_dtls_got_timeout(ssl_s), 1);
ExpectNotNull(SERVER_CID());
}
/* Client second flight */
wolfSSL_SetLoggingPrefix("client");
ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
ExpectNotNull(CLIENT_CID());
if (run_params[j].drop) {
test_memio_clear_buffer(&test_ctx, 0);
test_memio_clear_buffer(&test_ctx, 1);
ExpectIntEQ(wolfSSL_dtls_got_timeout(ssl_c), 1);
ExpectNotNull(CLIENT_CID());
}
ExpectIntEQ(wolfSSL_write(ssl_c, params[i],
(int)XSTRLEN(params[i])), XSTRLEN(params[i]));
/* Server second flight */
wolfSSL_SetLoggingPrefix("server");
ExpectIntEQ(wolfSSL_negotiate(ssl_s), 1);
XMEMSET(readBuf, 0, sizeof(readBuf));
ExpectIntEQ(wolfSSL_read(ssl_s, readBuf, sizeof(readBuf)),
XSTRLEN(params[i]));
ExpectStrEQ(readBuf, params[i]);
if (!run_params[j].drop) {
ExpectIntEQ(wolfSSL_write(ssl_s, params[i],
(int)XSTRLEN(params[i])), XSTRLEN(params[i]));
}
/* Test loading old epoch */
/* Client complete connection */
wolfSSL_SetLoggingPrefix("client");
if (!run_params[j].drop) {
ExpectIntEQ(wolfSSL_negotiate(ssl_c), 1);
XMEMSET(readBuf, 0, sizeof(readBuf));
ExpectIntEQ(wolfSSL_read(ssl_c, readBuf, sizeof(readBuf)),
XSTRLEN(params[i]));
ExpectStrEQ(readBuf, params[i]);
}
ExpectIntEQ(wolfSSL_negotiate(ssl_c), 1);
ExpectNull(CLIENT_CID());
ExpectIntEQ(wolfSSL_SSL_renegotiate_pending(ssl_c), 0);
ExpectIntEQ(wolfSSL_SSL_renegotiate_pending(ssl_s), 0);
#endif
/* Close connection */
wolfSSL_SetLoggingPrefix("client");
ExpectIntEQ(wolfSSL_shutdown(ssl_c), WOLFSSL_SHUTDOWN_NOT_DONE);
ExpectNotNull(CLIENT_CID());
wolfSSL_SetLoggingPrefix("server");
ExpectIntEQ(wolfSSL_shutdown(ssl_s), WOLFSSL_SHUTDOWN_NOT_DONE);
ExpectNotNull(SERVER_CID());
wolfSSL_SetLoggingPrefix("client");
ExpectIntEQ(wolfSSL_shutdown(ssl_c), 1);
wolfSSL_SetLoggingPrefix("server");
ExpectIntEQ(wolfSSL_shutdown(ssl_s), 1);
#ifdef HAVE_SECURE_RENEGOTIATION
loop_exit:
#endif
wolfSSL_SetLoggingPrefix(NULL);
wolfSSL_free(ssl_c);
wolfSSL_CTX_free(ctx_c);
wolfSSL_free(ssl_s);
wolfSSL_CTX_free(ctx_s);
if (EXPECT_SUCCESS())
printf("ok\n");
else
printf("failed\n");
}
}
#undef CLIENT_CID
#undef SERVER_CID
#undef RESET_CID
#endif
return EXPECT_RESULT();
}
int test_dtls13_basic_connection_id(void)
{
EXPECT_DECLS;
#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_DTLS13) \
&& defined(WOLFSSL_DTLS_CID)
unsigned char client_cid[] = { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
unsigned char server_cid[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
unsigned char readBuf[50];
void * cid = NULL;
const char* params[] = {
#ifndef NO_SHA256
#ifdef WOLFSSL_AES_128
#ifdef HAVE_AESGCM
"TLS13-AES128-GCM-SHA256",
#endif
#if defined(HAVE_CHACHA) && defined(HAVE_POLY1305)
"TLS13-CHACHA20-POLY1305-SHA256",
#endif
#ifdef HAVE_AESCCM
"TLS13-AES128-CCM-8-SHA256",
"TLS13-AES128-CCM-SHA256",
#endif
#endif
#ifdef HAVE_NULL_CIPHER
"TLS13-SHA256-SHA256",
#endif
#endif
};
size_t i;
/* We check if the side included the CID in their output */
#define CLIENT_CID() mymemmem(test_ctx.s_buff, test_ctx.s_len, \
client_cid, sizeof(client_cid))
#define SERVER_CID() mymemmem(test_ctx.c_buff, test_ctx.c_len, \
server_cid, sizeof(server_cid))
#define RESET_CID(cid) if ((cid) != NULL) { \
((char*)(cid))[0] = -1; \
}
printf("\n");
for (i = 0; i < XELEM_CNT(params) && EXPECT_SUCCESS(); i++) {
WOLFSSL_CTX *ctx_c = NULL, *ctx_s = NULL;
WOLFSSL *ssl_c = NULL, *ssl_s = NULL;
struct test_memio_ctx test_ctx;
printf("Testing %s ... ", params[i]);
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method), 0);
ExpectIntEQ(wolfSSL_set_cipher_list(ssl_c, params[i]), WOLFSSL_SUCCESS);
ExpectIntEQ(wolfSSL_set_cipher_list(ssl_s, params[i]), WOLFSSL_SUCCESS);
ExpectIntEQ(wolfSSL_dtls_cid_use(ssl_c), 1);
ExpectIntEQ(wolfSSL_dtls_cid_set(ssl_c, server_cid, sizeof(server_cid)),
1);
ExpectIntEQ(wolfSSL_dtls_cid_use(ssl_s), 1);
ExpectIntEQ(wolfSSL_dtls_cid_set(ssl_s, client_cid, sizeof(client_cid)),
1);
/* CH1 */
ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
ExpectNull(CLIENT_CID());
/* HRR */
ExpectIntEQ(wolfSSL_negotiate(ssl_s), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ);
ExpectNull(SERVER_CID());
/* CH2 */
ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
ExpectNull(CLIENT_CID());
/* Server first flight */
ExpectIntEQ(wolfSSL_negotiate(ssl_s), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ);
ExpectNotNull(SERVER_CID());
/* Client second flight */
ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
ExpectNotNull(CLIENT_CID());
/* Server process flight */
ExpectIntEQ(wolfSSL_negotiate(ssl_s), 1);
/* Client process flight */
ExpectIntEQ(wolfSSL_negotiate(ssl_c), 1);
/* Write some data */
ExpectIntEQ(wolfSSL_write(ssl_c, params[i], (int)XSTRLEN(params[i])),
XSTRLEN(params[i]));
ExpectNotNull(CLIENT_CID());
ExpectIntEQ(wolfSSL_write(ssl_s, params[i], (int)XSTRLEN(params[i])),
XSTRLEN(params[i]));
ExpectNotNull(SERVER_CID());
/* Read the data */
XMEMSET(readBuf, 0, sizeof(readBuf));
ExpectIntEQ(wolfSSL_read(ssl_c, readBuf, sizeof(readBuf)),
XSTRLEN(params[i]));
ExpectStrEQ(readBuf, params[i]);
XMEMSET(readBuf, 0, sizeof(readBuf));
ExpectIntEQ(wolfSSL_read(ssl_s, readBuf, sizeof(readBuf)),
XSTRLEN(params[i]));
ExpectStrEQ(readBuf, params[i]);
/* Write short data */
ExpectIntEQ(wolfSSL_write(ssl_c, params[i], 1), 1);
ExpectNotNull(CLIENT_CID());
ExpectIntEQ(wolfSSL_write(ssl_s, params[i], 1), 1);
ExpectNotNull(SERVER_CID());
/* Read the short data */
XMEMSET(readBuf, 0, sizeof(readBuf));
ExpectIntEQ(wolfSSL_read(ssl_c, readBuf, sizeof(readBuf)), 1);
ExpectIntEQ(readBuf[0], params[i][0]);
XMEMSET(readBuf, 0, sizeof(readBuf));
ExpectIntEQ(wolfSSL_read(ssl_s, readBuf, sizeof(readBuf)), 1);
ExpectIntEQ(readBuf[0], params[i][0]);
/* Write some data but with wrong CID */
ExpectIntEQ(wolfSSL_write(ssl_c, params[i], (int)XSTRLEN(params[i])),
XSTRLEN(params[i]));
/* Reset client cid. */
ExpectNotNull(cid = CLIENT_CID());
RESET_CID(cid);
ExpectIntEQ(wolfSSL_write(ssl_s, params[i], (int)XSTRLEN(params[i])),
XSTRLEN(params[i]));
/* Reset server cid. */
ExpectNotNull(cid = SERVER_CID());
RESET_CID(cid);
/* Try to read the data but it shouldn't be there */
ExpectIntEQ(wolfSSL_read(ssl_c, readBuf, sizeof(readBuf)), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
ExpectIntEQ(wolfSSL_read(ssl_s, readBuf, sizeof(readBuf)), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ);
/* Close connection */
ExpectIntEQ(wolfSSL_shutdown(ssl_c), WOLFSSL_SHUTDOWN_NOT_DONE);
ExpectNotNull(CLIENT_CID());
ExpectIntEQ(wolfSSL_shutdown(ssl_s), WOLFSSL_SHUTDOWN_NOT_DONE);
ExpectNotNull(SERVER_CID());
ExpectIntEQ(wolfSSL_shutdown(ssl_c), 1);
ExpectIntEQ(wolfSSL_shutdown(ssl_s), 1);
if (EXPECT_SUCCESS())
printf("ok\n");
else
printf("failed\n");
wolfSSL_free(ssl_c);
wolfSSL_CTX_free(ctx_c);
wolfSSL_free(ssl_s);
wolfSSL_CTX_free(ctx_s);
}
#undef CLIENT_CID
#undef SERVER_CID
#undef RESET_CID
#endif
return EXPECT_RESULT();
}
/** Test DTLS 1.3 behavior when server hits WANT_WRITE during HRR
* The test sets up a DTLS 1.3 connection where the server is forced to
* return WANT_WRITE when sending the HelloRetryRequest. After the handshake,
* application data is exchanged in both directions to verify the connection
* works as expected.
*/
int test_dtls13_hrr_want_write(void)
{
EXPECT_DECLS;
#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_DTLS13)
WOLFSSL_CTX *ctx_c = NULL, *ctx_s = NULL;
WOLFSSL *ssl_c = NULL, *ssl_s = NULL;
const char msg[] = "hello";
const int msgLen = sizeof(msg);
struct test_memio_ctx test_ctx;
char readBuf[sizeof(msg)];
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method),
0);
/* Client sends first ClientHello */
ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
/* Force server to hit WANT_WRITE when producing the HRR */
test_memio_simulate_want_write(&test_ctx, 0, 1);
ExpectIntEQ(wolfSSL_negotiate(ssl_s), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_WRITE);
/* Allow the server to flush the HRR and proceed */
test_memio_simulate_want_write(&test_ctx, 0, 0);
ExpectIntEQ(wolfSSL_negotiate(ssl_s), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ);
/* Resume the DTLS 1.3 handshake */
ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0);
/* Verify post-handshake application data in both directions */
XMEMSET(readBuf, 0, sizeof(readBuf));
ExpectIntEQ(wolfSSL_write(ssl_c, msg, msgLen), msgLen);
ExpectIntEQ(wolfSSL_read(ssl_s, readBuf, sizeof(readBuf)), msgLen);
ExpectStrEQ(readBuf, msg);
XMEMSET(readBuf, 0, sizeof(readBuf));
ExpectIntEQ(wolfSSL_write(ssl_s, msg, msgLen), msgLen);
ExpectIntEQ(wolfSSL_read(ssl_c, readBuf, sizeof(readBuf)), msgLen);
ExpectStrEQ(readBuf, msg);
wolfSSL_free(ssl_c);
wolfSSL_CTX_free(ctx_c);
wolfSSL_free(ssl_s);
wolfSSL_CTX_free(ctx_s);
#endif
return EXPECT_RESULT();
}
#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_DTLS13)
struct test_dtls13_wwrite_ctx {
int want_write;
struct test_memio_ctx *text_ctx;
};
static int test_dtls13_want_write_send_cb(WOLFSSL *ssl, char *data, int sz, void *ctx)
{
struct test_dtls13_wwrite_ctx *wwctx = (struct test_dtls13_wwrite_ctx *)ctx;
wwctx->want_write = !wwctx->want_write;
if (wwctx->want_write) {
return WOLFSSL_CBIO_ERR_WANT_WRITE;
}
return test_memio_write_cb(ssl, data, sz, wwctx->text_ctx);
}
#endif
/** Test DTLS 1.3 behavior when every other write returns WANT_WRITE
* The test sets up a DTLS 1.3 connection where both client and server
* alternate between WANT_WRITE and successful writes. After the handshake,
* application data is exchanged in both directions to verify the connection
* works as expected.
*
* Data exchanged after the handshake is also tested with simulated WANT_WRITE
* conditions to ensure the connection remains functional.
*/
int test_dtls13_every_write_want_write(void)
{
EXPECT_DECLS;
#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_DTLS13)
WOLFSSL_CTX *ctx_c = NULL, *ctx_s = NULL;
WOLFSSL *ssl_c = NULL, *ssl_s = NULL;
struct test_memio_ctx test_ctx;
const char msg[] = "want-write";
const int msgLen = sizeof(msg);
char readBuf[sizeof(msg)];
struct test_dtls13_wwrite_ctx wwctx_c;
struct test_dtls13_wwrite_ctx wwctx_s;
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method),
0);
wwctx_c.want_write = 0;
wwctx_c.text_ctx = &test_ctx;
wolfSSL_SetIOWriteCtx(ssl_c, &wwctx_c);
wolfSSL_SSLSetIOSend(ssl_c, test_dtls13_want_write_send_cb);
wwctx_s.want_write = 0;
wwctx_s.text_ctx = &test_ctx;
wolfSSL_SetIOWriteCtx(ssl_s, &wwctx_s);
wolfSSL_SSLSetIOSend(ssl_s, test_dtls13_want_write_send_cb);
ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 20, NULL), 0);
ExpectTrue(wolfSSL_is_init_finished(ssl_c));
ExpectTrue(wolfSSL_is_init_finished(ssl_s));
test_memio_simulate_want_write(&test_ctx, 0, 0);
test_memio_simulate_want_write(&test_ctx, 1, 0);
wolfSSL_SetIOWriteCtx(ssl_c, &test_ctx);
wolfSSL_SSLSetIOSend(ssl_c, test_memio_write_cb);
wolfSSL_SetIOWriteCtx(ssl_s, &test_ctx);
wolfSSL_SSLSetIOSend(ssl_s, test_memio_write_cb);
XMEMSET(readBuf, 0, sizeof(readBuf));
ExpectIntEQ(wolfSSL_write(ssl_c, msg, msgLen), msgLen);
ExpectIntEQ(wolfSSL_read(ssl_s, readBuf, sizeof(readBuf)), msgLen);
ExpectStrEQ(readBuf, msg);
XMEMSET(readBuf, 0, sizeof(readBuf));
ExpectIntEQ(wolfSSL_write(ssl_s, msg, msgLen), msgLen);
ExpectIntEQ(wolfSSL_read(ssl_c, readBuf, sizeof(readBuf)), msgLen);
ExpectStrEQ(readBuf, msg);
test_memio_simulate_want_write(&test_ctx, 0, 1);
XMEMSET(readBuf, 0, sizeof(readBuf));
ExpectIntEQ(wolfSSL_write(ssl_s, msg, msgLen), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_WRITE);
test_memio_simulate_want_write(&test_ctx, 0, 0);
ExpectIntEQ(wolfSSL_write(ssl_s, msg, msgLen), msgLen);
ExpectIntEQ(wolfSSL_read(ssl_c, readBuf, sizeof(readBuf)), msgLen);
ExpectStrEQ(readBuf, msg);
XMEMSET(readBuf, 0, sizeof(readBuf));
test_memio_simulate_want_write(&test_ctx, 1, 1);
ExpectIntEQ(wolfSSL_write(ssl_c, msg, msgLen), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_WRITE);
test_memio_simulate_want_write(&test_ctx, 1, 0);
ExpectIntEQ(wolfSSL_write(ssl_c, msg, msgLen), msgLen);
ExpectIntEQ(wolfSSL_read(ssl_s, readBuf, sizeof(readBuf)), msgLen);
ExpectStrEQ(readBuf, msg);
wolfSSL_free(ssl_c);
wolfSSL_CTX_free(ctx_c);
wolfSSL_free(ssl_s);
wolfSSL_CTX_free(ctx_s);
#endif
return EXPECT_RESULT();
}
int test_wolfSSL_dtls_cid_parse(void)
{
EXPECT_DECLS;
#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_DTLS_CID)
/* Taken from Wireshark. Right-click -> copy -> ... as escaped string */
/* Plaintext ServerHelloDone. No CID. */
byte noCid[] =
"\x16\xfe\xfd\x00\x00\x00\x00\x00\x00\x00\x04\x00\x0c\x0e\x00\x00" \
"\x00\x00\x04\x00\x00\x00\x00\x00\x00";
/* 1.2 app data containing CID */
byte cid12[] =
"\x19\xfe\xfd\x00\x01\x00\x00\x00\x00\x00\x01\x77\xa3\x79\x34\xb3" \
"\xf1\x1f\x34\x00\x1f\xdb\x8c\x28\x25\x9f\xe1\x02\x26\x77\x1c\x3a" \
"\x50\x1b\x50\x99\xd0\xb5\x20\xd8\x2c\x2e\xaa\x36\x36\xe0\xb7\xb7" \
"\xf7\x7d\xff\xb0";
#ifdef WOLFSSL_DTLS13
/* 1.3 app data containing CID */
byte cid13[] =
"\x3f\x70\x64\x04\xc6\xfb\x97\x21\xd9\x28\x27\x00\x17\xc1\x01\x86" \
"\xe7\x23\x2c\xad\x65\x83\xa8\xf4\xbf\xbf\x7b\x25\x16\x80\x19\xc3" \
"\x81\xda\xf5\x3f";
#endif
ExpectPtrEq(wolfSSL_dtls_cid_parse(noCid, sizeof(noCid), 8), NULL);
ExpectPtrEq(wolfSSL_dtls_cid_parse(cid12, sizeof(cid12), 8), cid12 + 11);
#ifdef WOLFSSL_DTLS13
ExpectPtrEq(wolfSSL_dtls_cid_parse(cid13, sizeof(cid13), 8), cid13 + 1);
#endif
#endif
return EXPECT_RESULT();
}
int test_wolfSSL_dtls_set_pending_peer(void)
{
EXPECT_DECLS;
#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \
defined(WOLFSSL_DTLS) && defined(WOLFSSL_DTLS_CID)
WOLFSSL_CTX *ctx_c = NULL, *ctx_s = NULL;
WOLFSSL *ssl_c = NULL, *ssl_s = NULL;
struct test_memio_ctx test_ctx;
unsigned char peer[10];
unsigned int peerSz;
unsigned char readBuf[10];
unsigned char client_cid[] = { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
unsigned char server_cid[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
/* Setup DTLS contexts */
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
wolfDTLS_client_method, wolfDTLS_server_method), 0);
ExpectIntEQ(wolfSSL_dtls_cid_use(ssl_c), 1);
ExpectIntEQ(wolfSSL_dtls_cid_set(ssl_c, server_cid,
sizeof(server_cid)), 1);
ExpectIntEQ(wolfSSL_dtls_cid_use(ssl_s), 1);
ExpectIntEQ(wolfSSL_dtls_cid_set(ssl_s, client_cid,
sizeof(client_cid)), 1);
ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0);
peerSz = sizeof(peer);
/* Fail since no peer set */
ExpectIntEQ(wolfSSL_dtls_get_peer(ssl_s, peer, &peerSz), 0);
ExpectIntEQ(wolfSSL_dtls_set_pending_peer(ssl_s, (void*)"123", 4), 1);
ExpectIntEQ(wolfSSL_write(ssl_c, "test", 5), 5);
ExpectIntEQ(wolfSSL_read(ssl_s, readBuf, sizeof(readBuf)), 5);
ExpectStrEQ(readBuf, "test");
peerSz = sizeof(peer);
ExpectIntEQ(wolfSSL_dtls_get_peer(ssl_s, peer, &peerSz), 1);
ExpectIntEQ(peerSz, 4);
ExpectStrEQ(peer, "123");
wolfSSL_free(ssl_s);
wolfSSL_free(ssl_c);
wolfSSL_CTX_free(ctx_s);
wolfSSL_CTX_free(ctx_c);
#endif
return EXPECT_RESULT();
}
int test_dtls13_epochs(void) {
EXPECT_DECLS;
#if defined(WOLFSSL_DTLS13) && !defined(NO_WOLFSSL_CLIENT)
WOLFSSL_CTX* ctx = NULL;
WOLFSSL* ssl = NULL;
byte input[20];
word32 inOutIdx = 0;
XMEMSET(input, 0, sizeof(input));
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfDTLSv1_3_client_method()));
ExpectNotNull(ssl = wolfSSL_new(ctx));
/* Some manual setup to enter the epoch check */
ExpectTrue(ssl->options.tls1_3 = 1);
inOutIdx = 0;
if (ssl != NULL) ssl->keys.curEpoch64 = w64From32(0x0, 0x0);
ExpectIntEQ(DoApplicationData(ssl, input, &inOutIdx, 0), SANITY_MSG_E);
inOutIdx = 0;
if (ssl != NULL) ssl->keys.curEpoch64 = w64From32(0x0, 0x2);
ExpectIntEQ(DoApplicationData(ssl, input, &inOutIdx, 0), SANITY_MSG_E);
if (ssl != NULL) ssl->keys.curEpoch64 = w64From32(0x0, 0x1);
ExpectIntEQ(Dtls13CheckEpoch(ssl, client_hello), SANITY_MSG_E);
ExpectIntEQ(Dtls13CheckEpoch(ssl, server_hello), SANITY_MSG_E);
ExpectIntEQ(Dtls13CheckEpoch(ssl, hello_verify_request), SANITY_MSG_E);
ExpectIntEQ(Dtls13CheckEpoch(ssl, hello_retry_request), SANITY_MSG_E);
ExpectIntEQ(Dtls13CheckEpoch(ssl, hello_request), SANITY_MSG_E);
ExpectIntEQ(Dtls13CheckEpoch(ssl, encrypted_extensions), SANITY_MSG_E);
ExpectIntEQ(Dtls13CheckEpoch(ssl, server_key_exchange), SANITY_MSG_E);
ExpectIntEQ(Dtls13CheckEpoch(ssl, server_hello_done), SANITY_MSG_E);
ExpectIntEQ(Dtls13CheckEpoch(ssl, client_key_exchange), SANITY_MSG_E);
ExpectIntEQ(Dtls13CheckEpoch(ssl, certificate_request), SANITY_MSG_E);
ExpectIntEQ(Dtls13CheckEpoch(ssl, certificate), SANITY_MSG_E);
ExpectIntEQ(Dtls13CheckEpoch(ssl, certificate_verify), SANITY_MSG_E);
ExpectIntEQ(Dtls13CheckEpoch(ssl, finished), SANITY_MSG_E);
ExpectIntEQ(Dtls13CheckEpoch(ssl, certificate_status), SANITY_MSG_E);
ExpectIntEQ(Dtls13CheckEpoch(ssl, change_cipher_hs), SANITY_MSG_E);
ExpectIntEQ(Dtls13CheckEpoch(ssl, key_update), SANITY_MSG_E);
ExpectIntEQ(Dtls13CheckEpoch(ssl, session_ticket), SANITY_MSG_E);
ExpectIntEQ(Dtls13CheckEpoch(ssl, end_of_early_data), SANITY_MSG_E);
ExpectIntEQ(Dtls13CheckEpoch(ssl, message_hash), SANITY_MSG_E);
ExpectIntEQ(Dtls13CheckEpoch(ssl, no_shake), SANITY_MSG_E);
wolfSSL_CTX_free(ctx);
wolfSSL_free(ssl);
#endif
return EXPECT_RESULT();
}
int test_dtls13_ack_order(void)
{
EXPECT_DECLS;
#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_DTLS13)
WOLFSSL_CTX *ctx_c = NULL, *ctx_s = NULL;
WOLFSSL *ssl_c = NULL, *ssl_s = NULL;
struct test_memio_ctx test_ctx;
unsigned char readBuf[50];
word32 length = 0;
/* struct {
* uint64 epoch;
* uint64 sequence_number;
* } RecordNumber;
* Big endian */
static const unsigned char expected_output[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06,
};
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
/* Get a populated DTLS object */
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method), 0);
ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0);
ExpectIntEQ(wolfSSL_read(ssl_c, readBuf, sizeof(readBuf)), -1);
/* Clear the buffer of any extra messages */
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
ExpectIntEQ(wolfSSL_read(ssl_s, readBuf, sizeof(readBuf)), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ);
ExpectIntEQ(test_ctx.c_len, 0);
ExpectIntEQ(test_ctx.s_len, 0);
/* Add seen records */
ExpectIntEQ(Dtls13RtxAddAck(ssl_c, w64From32(0, 3), w64From32(0, 2)), 0);
ExpectIntEQ(Dtls13RtxAddAck(ssl_c, w64From32(0, 3), w64From32(0, 0)), 0);
ExpectIntEQ(Dtls13RtxAddAck(ssl_c, w64From32(0, 3), w64From32(0, 1)), 0);
ExpectIntEQ(Dtls13RtxAddAck(ssl_c, w64From32(0, 3), w64From32(0, 4)), 0);
ExpectIntEQ(Dtls13RtxAddAck(ssl_c, w64From32(0, 2), w64From32(0, 0)), 0);
ExpectIntEQ(Dtls13RtxAddAck(ssl_c, w64From32(0, 3), w64From32(0, 6)), 0);
ExpectIntEQ(Dtls13RtxAddAck(ssl_c, w64From32(0, 3), w64From32(0, 6)), 0);
ExpectIntEQ(Dtls13RtxAddAck(ssl_c, w64From32(0, 2), w64From32(0, 1)), 0);
ExpectIntEQ(Dtls13RtxAddAck(ssl_c, w64From32(0, 2), w64From32(0, 2)), 0);
ExpectIntEQ(Dtls13RtxAddAck(ssl_c, w64From32(0, 2), w64From32(0, 2)), 0);
ExpectIntEQ(Dtls13WriteAckMessage(ssl_c, ssl_c->dtls13Rtx.seenRecords,
&length), 0);
/* must zero the span reserved for the header to avoid read of uninited
* data.
*/
XMEMSET(ssl_c->buffers.outputBuffer.buffer, 0,
5 /* DTLS13_UNIFIED_HEADER_SIZE */);
/* N * RecordNumber + 2 extra bytes for length */
ExpectIntEQ(length, sizeof(expected_output) + 2);
ExpectNotNull(mymemmem(ssl_c->buffers.outputBuffer.buffer,
ssl_c->buffers.outputBuffer.bufferSize, expected_output,
sizeof(expected_output)));
wolfSSL_free(ssl_c);
wolfSSL_CTX_free(ctx_c);
wolfSSL_free(ssl_s);
wolfSSL_CTX_free(ctx_s);
#endif
return EXPECT_RESULT();
}
int test_dtls_version_checking(void)
{
EXPECT_DECLS;
#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_DTLS)
WOLFSSL_CTX *ctx_c = NULL, *ctx_s = NULL;
WOLFSSL *ssl_c = NULL, *ssl_s = NULL;
struct test_memio_ctx test_ctx;
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
wolfDTLSv1_2_client_method, wolfDTLSv1_2_server_method),
0);
/* CH */
ExpectIntEQ(wolfSSL_connect(ssl_c), WOLFSSL_FATAL_ERROR);
ExpectIntEQ(wolfSSL_get_error(ssl_c, WOLFSSL_FATAL_ERROR),
WOLFSSL_ERROR_WANT_READ);
/* modify CH DTLS header to have version 1.1 (0xfe, 0xfe) */
ExpectIntGE(test_ctx.s_len, 3);
if (EXPECT_SUCCESS()) {
test_ctx.s_buff[1] = 0xfe;
test_ctx.s_buff[2] = 0xfe;
}
ExpectIntEQ(wolfSSL_accept(ssl_s), WOLFSSL_FATAL_ERROR);
ExpectIntEQ(wolfSSL_get_error(ssl_s, WOLFSSL_FATAL_ERROR),
WOLFSSL_ERROR_WANT_READ);
/* server should drop the message */
ExpectIntEQ(test_ctx.c_len, 0);
wolfSSL_free(ssl_c);
ssl_c = wolfSSL_new(ctx_c);
ExpectNotNull(ssl_c);
wolfSSL_SetIOWriteCtx(ssl_c, &test_ctx);
wolfSSL_SetIOReadCtx(ssl_c, &test_ctx);
/* try again */
ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0);
wolfSSL_free(ssl_c);
wolfSSL_CTX_free(ctx_c);
wolfSSL_free(ssl_s);
wolfSSL_CTX_free(ctx_s);
#endif /* HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES && WOLFSSL_DTLS */
return EXPECT_RESULT();
}
#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_DTLS)
static int test_dtls_shutdown(WOLFSSL *s, WOLFSSL *c, WOLFSSL_CTX *cc, WOLFSSL_CTX *cs)
{
EXPECT_DECLS;
/* Cleanup */
wolfSSL_SetLoggingPrefix("client");
ExpectIntEQ(wolfSSL_shutdown(c), WOLFSSL_SHUTDOWN_NOT_DONE);
wolfSSL_SetLoggingPrefix("server");
ExpectIntEQ(wolfSSL_shutdown(s), WOLFSSL_SHUTDOWN_NOT_DONE);
wolfSSL_SetLoggingPrefix("client");
ExpectIntEQ(wolfSSL_shutdown(c), 1);
wolfSSL_SetLoggingPrefix("server");
ExpectIntEQ(wolfSSL_shutdown(s), 1);
wolfSSL_SetLoggingPrefix(NULL);
wolfSSL_free(c);
wolfSSL_CTX_free(cc);
wolfSSL_free(s);
wolfSSL_CTX_free(cs);
return EXPECT_RESULT();
}
static int test_dtls_communication(WOLFSSL *s, WOLFSSL *c)
{
EXPECT_DECLS;
unsigned char readBuf[50];
wolfSSL_SetLoggingPrefix("client");
ExpectIntEQ(wolfSSL_write(c, "client message", 14), 14);
wolfSSL_SetLoggingPrefix("server");
XMEMSET(readBuf, 0, sizeof(readBuf));
ExpectIntEQ(wolfSSL_read(s, readBuf, sizeof(readBuf)), 14);
ExpectStrEQ(readBuf, "client message");
wolfSSL_SetLoggingPrefix("server");
ExpectIntEQ(wolfSSL_write(s, "server message", 14), 14);
wolfSSL_SetLoggingPrefix("client");
XMEMSET(readBuf, 0, sizeof(readBuf));
ExpectIntEQ(wolfSSL_read(c, readBuf, sizeof(readBuf)), 14);
ExpectStrEQ(readBuf, "server message");
/* this extra round is consuming newSessionTicket and acks */
wolfSSL_SetLoggingPrefix("client");
ExpectIntEQ(wolfSSL_write(c, "client message 2", 16), 16);
wolfSSL_SetLoggingPrefix("server");
XMEMSET(readBuf, 0, sizeof(readBuf));
ExpectIntEQ(wolfSSL_read(s, readBuf, sizeof(readBuf)), 16);
ExpectStrEQ(readBuf, "client message 2");
wolfSSL_SetLoggingPrefix("server");
ExpectIntEQ(wolfSSL_write(s, "server message 2", 16), 16);
wolfSSL_SetLoggingPrefix("client");
XMEMSET(readBuf, 0, sizeof(readBuf));
ExpectIntEQ(wolfSSL_read(c, readBuf, sizeof(readBuf)), 16);
ExpectStrEQ(readBuf, "server message 2");
return EXPECT_RESULT();
}
#if defined(WOLFSSL_DTLS13) && !defined(WOLFSSL_DTLS_RECORDS_CAN_SPAN_DATAGRAMS)
int test_dtls13_longer_length(void)
{
EXPECT_DECLS;
WOLFSSL_CTX *ctx_c = NULL, *ctx_s = NULL;
WOLFSSL *ssl_c = NULL, *ssl_s = NULL;
struct test_memio_ctx test_ctx;
unsigned char readBuf[50];
int seq16bit = 0;
int ret;
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
/* Setup DTLS contexts */
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method),
0);
/* Complete handshake */
ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0);
/* Create good record with length mismatch */
wolfSSL_SetLoggingPrefix("client");
ExpectIntEQ(wolfSSL_write(ssl_c, "client message", 14), 14);
/* check client wrote the record */
ExpectIntGT(test_ctx.s_len, 14);
/* check length is included in the record header */
ExpectIntGT(test_ctx.s_buff[0x0] & (1 << 2), 0);
seq16bit = (test_ctx.s_buff[0x0] & (1 << 3)) != 0;
/* big endian, modify LSB byte */
seq16bit *= 2;
/* modify length to be bigger */
test_ctx.s_buff[0x2 + seq16bit] = 0xff;
/* Try to read the malformed record */
wolfSSL_SetLoggingPrefix("server");
ExpectIntEQ(wolfSSL_read(ssl_s, readBuf, sizeof(readBuf)), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ);
ExpectIntEQ(test_ctx.s_len, 0);
ExpectIntEQ(test_dtls_communication(ssl_s, ssl_c), TEST_SUCCESS);
ret = test_dtls_shutdown(ssl_s, ssl_c, ctx_c, ctx_s);
ExpectIntEQ(ret, TEST_SUCCESS);
return EXPECT_RESULT();
}
#else
int test_dtls13_longer_length(void)
{
return TEST_SKIPPED;
}
#endif /* WOLFSSL_DTLS13 && !defined(WOLFSSL_DTLS_RECORDS_CAN_SPAN_DATAGRAMS) */
#if defined(WOLFSSL_DTLS13) && !defined(WOLFSSL_DTLS_RECORDS_CAN_SPAN_DATAGRAMS)
int test_dtls13_short_read(void)
{
EXPECT_DECLS;
WOLFSSL_CTX *ctx_c = NULL, *ctx_s = NULL;
WOLFSSL *ssl_c = NULL, *ssl_s = NULL;
struct test_memio_ctx test_ctx;
unsigned char readBuf[50];
int i;
int ret;
/* we setup two test, in the first one the server reads just two bytes of
* the header, in the second one it reads just the header (5) */
for (i = 0; i < 2; i++) {
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
/* Setup DTLS contexts */
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method),
0);
/* Complete handshake */
ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0);
/* create a good record in the buffer */
wolfSSL_SetLoggingPrefix("client");
ExpectIntEQ(wolfSSL_write(ssl_c, "client message", 14), 14);
/* check client wrote the record */
ExpectIntGT(test_ctx.s_len, 14);
/* return less data */
ExpectIntEQ(
test_memio_modify_message_len(&test_ctx, 0, 0, i == 0 ? 2 : 5), 0);
/* Try to read the malformed record */
wolfSSL_SetLoggingPrefix("server");
ExpectIntEQ(wolfSSL_read(ssl_s, readBuf, sizeof(readBuf)), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ);
ExpectIntEQ(test_ctx.s_len, 0);
ExpectIntEQ(test_dtls_communication(ssl_s, ssl_c), TEST_SUCCESS);
ret = test_dtls_shutdown(ssl_s, ssl_c, ctx_c, ctx_s);
ExpectIntEQ(ret, TEST_SUCCESS);
ssl_c = ssl_s = NULL;
ctx_c = ctx_s = NULL;
}
return EXPECT_RESULT();
}
#else
int test_dtls13_short_read(void)
{
return TEST_SKIPPED;
}
#endif /* WOLFSSL_DTLS13 && !defined(WOLFSSL_DTLS_RECORDS_CAN_SPAN_DATAGRAMS) */
#if !defined(WOLFSSL_DTLS_RECORDS_CAN_SPAN_DATAGRAMS)
int test_dtls12_short_read(void)
{
EXPECT_DECLS;
WOLFSSL_CTX *ctx_c = NULL, *ctx_s = NULL;
WOLFSSL *ssl_c = NULL, *ssl_s = NULL;
struct test_memio_ctx test_ctx;
unsigned char readBuf[50];
int i;
int ret;
for (i = 0; i < 3; i++) {
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
/* Setup DTLS contexts */
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
wolfDTLSv1_2_client_method, wolfDTLSv1_2_server_method),
0);
/* Complete handshake */
ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0);
/* create a good record in the buffer */
wolfSSL_SetLoggingPrefix("client");
ExpectIntEQ(wolfSSL_write(ssl_c, "bad", 3), 3);
/* check client wrote the record */
ExpectIntGT(test_ctx.s_len, 13 + 3);
/* return less data */
switch (i) {
case 0:
ExpectIntEQ(test_memio_modify_message_len(&test_ctx, 0, 0, 2), 0);
break;
case 1:
ExpectIntEQ(test_memio_modify_message_len(&test_ctx, 0, 0, 13), 0);
break;
case 2:
ExpectIntEQ(test_memio_modify_message_len(&test_ctx, 0, 0, 15), 0);
break;
}
/* Try to read the malformed record */
wolfSSL_SetLoggingPrefix("server");
ExpectIntEQ(wolfSSL_read(ssl_s, readBuf, sizeof(readBuf)), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ);
ExpectIntEQ(test_ctx.s_len, 0);
ExpectIntEQ(test_dtls_communication(ssl_s, ssl_c), TEST_SUCCESS);
ret = test_dtls_shutdown(ssl_s, ssl_c, ctx_c, ctx_s);
ExpectIntEQ(ret, TEST_SUCCESS);
ssl_c = ssl_s = NULL;
ctx_c = ctx_s = NULL;
}
return EXPECT_RESULT();
}
#else
int test_dtls12_short_read(void)
{
return TEST_SKIPPED;
}
#endif /* !defined(WOLFSSL_DTLS_RECORDS_CAN_SPAN_DATAGRAMS) */
#if !defined(WOLFSSL_DTLS_RECORDS_CAN_SPAN_DATAGRAMS)
int test_dtls12_record_length_mismatch(void)
{
EXPECT_DECLS;
WOLFSSL_CTX *ctx_c = NULL, *ctx_s = NULL;
WOLFSSL *ssl_c = NULL, *ssl_s = NULL;
struct test_memio_ctx test_ctx;
unsigned char readBuf[50];
int ret;
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
/* Setup DTLS contexts */
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
wolfDTLSv1_2_client_method, wolfDTLSv1_2_server_method),
0);
/* Complete handshake */
ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0);
/* write a message from client */
ExpectIntEQ(wolfSSL_write(ssl_c, "bad", 3), 3);
/* check that the message is written in the buffer */
ExpectIntGT(test_ctx.s_len, 14);
/* modify the length field to be bigger than the content */
test_ctx.s_buff[12] = 0xff;
/* Try to read the malformed record */
wolfSSL_SetLoggingPrefix("server");
ExpectIntEQ(wolfSSL_read(ssl_s, readBuf, sizeof(readBuf)), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ);
ExpectIntEQ(test_ctx.s_len, 0);
ExpectIntEQ(test_dtls_communication(ssl_s, ssl_c), TEST_SUCCESS);
ret = test_dtls_shutdown(ssl_s, ssl_c, ctx_c, ctx_s);
ExpectIntEQ(ret, TEST_SUCCESS);
return EXPECT_RESULT();
}
int test_dtls_record_cross_boundaries(void)
{
EXPECT_DECLS;
WOLFSSL_CTX *ctx_c = NULL, *ctx_s = NULL;
WOLFSSL *ssl_c = NULL, *ssl_s = NULL;
struct test_memio_ctx test_ctx;
unsigned char readBuf[256];
int rec0_len, rec1_len;
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
/* Setup DTLS contexts */
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
wolfDTLSv1_2_client_method, wolfDTLSv1_2_server_method),
0);
/* Complete handshake */
ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0);
/* create a first record in the buffer */
wolfSSL_SetLoggingPrefix("client");
ExpectIntEQ(wolfSSL_write(ssl_c, "test0", 5), 5);
rec0_len = test_ctx.s_msg_sizes[0];
/* create a second record in the buffer */
ExpectIntEQ(wolfSSL_write(ssl_c, "test1", 5), 5);
rec1_len = test_ctx.s_msg_sizes[1];
ExpectIntLE(rec0_len + rec1_len, sizeof(readBuf));
if (EXPECT_SUCCESS())
XMEMCPY(readBuf, test_ctx.s_buff, rec0_len + rec1_len);
/* clear buffer */
test_memio_clear_buffer(&test_ctx, 0);
/* inject first record + 1 bytes of second record */
ExpectIntEQ(test_memio_inject_message(&test_ctx, 0, (const char*)readBuf,
rec0_len + 1),
0);
/* inject second record */
ExpectIntEQ(test_memio_inject_message(&test_ctx, 0,
(const char*)readBuf + rec0_len + 1, rec1_len - 1),
0);
ExpectIntEQ(test_ctx.s_len, rec0_len + rec1_len);
/* reading the record should return just the first message*/
wolfSSL_SetLoggingPrefix("server");
ExpectIntEQ(wolfSSL_read(ssl_s, readBuf, sizeof(readBuf)), 5);
ExpectBufEQ(readBuf, "test0", 5);
ExpectIntEQ(wolfSSL_read(ssl_s, readBuf, sizeof(readBuf)),
WOLFSSL_FATAL_ERROR);
ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ);
/* cleanup */
wolfSSL_free(ssl_s);
wolfSSL_free(ssl_c);
wolfSSL_CTX_free(ctx_s);
wolfSSL_CTX_free(ctx_c);
return EXPECT_RESULT();
}
#else
int test_dtls12_record_length_mismatch(void)
{
return TEST_SKIPPED;
}
int test_dtls_record_cross_boundaries(void)
{
return TEST_SKIPPED;
}
#endif /* !defined(WOLFSSL_DTLS_RECORDS_CAN_SPAN_DATAGRAMS) */
int test_dtls_short_ciphertext(void)
{
EXPECT_DECLS;
WOLFSSL_CTX *ctx_c = NULL, *ctx_s = NULL;
WOLFSSL *ssl_c = NULL, *ssl_s = NULL;
struct test_memio_ctx test_ctx;
unsigned char readBuf[50];
int ret;
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
/* Setup DTLS contexts */
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
wolfDTLSv1_2_client_method, wolfDTLSv1_2_server_method),
0);
/* Complete handshake */
ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0);
/* Create a message, that looks encrypted but shorter than minimum ciphertext length */
/* create the data in the buffer */
ExpectIntEQ(wolfSSL_write(ssl_c, "bad", 3), 3);
/* check client wrote the record */
ExpectIntGT(test_ctx.s_len, 14);
/* modify the length field to be smaller than the content */
test_ctx.s_buff[11] = 0x00;
test_ctx.s_buff[12] = 0x02;
/* modify the amount of data to send */
ExpectIntEQ(test_memio_modify_message_len(&test_ctx, 0, 0, 15), 0);
/* Try to read the malformed record */
wolfSSL_SetLoggingPrefix("server");
ExpectIntEQ(wolfSSL_read(ssl_s, readBuf, sizeof(readBuf)), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ);
ExpectIntEQ(test_ctx.s_len, 0);
ExpectIntEQ(test_dtls_communication(ssl_s, ssl_c), TEST_SUCCESS);
ret = test_dtls_shutdown(ssl_s, ssl_c, ctx_c, ctx_s);
ExpectIntEQ(ret, TEST_SUCCESS);
return EXPECT_RESULT();
}
#else
int test_dtls_short_ciphertext(void)
{
return TEST_SKIPPED;
}
int test_dtls12_record_length_mismatch(void)
{
return TEST_SKIPPED;
}
int test_dtls12_short_read(void)
{
return TEST_SKIPPED;
}
int test_dtls13_short_read(void)
{
return TEST_SKIPPED;
}
int test_dtls13_longer_length(void)
{
return TEST_SKIPPED;
}
int test_dtls_record_cross_boundaries(void)
{
return TEST_SKIPPED;
}
#endif /* defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_DTLS) */
#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \
!defined(WOLFSSL_NO_TLS12) && !defined(NO_SHA256)
/* This test that the DTLS record boundary check doesn't interfere with TLS
* records processing */
int test_records_span_network_boundaries(void)
{
EXPECT_DECLS;
WOLFSSL_CTX *ctx_c = NULL, *ctx_s = NULL;
WOLFSSL *ssl_c = NULL, *ssl_s = NULL;
struct test_memio_ctx test_ctx;
unsigned char readBuf[256];
int record_len;
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
/* Setup DTLS contexts */
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
wolfTLSv1_2_client_method, wolfTLSv1_2_server_method),
0);
/* Complete handshake */
ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0);
/* create a good record in the buffer */
wolfSSL_SetLoggingPrefix("client");
ExpectIntEQ(wolfSSL_write(ssl_c, "test", 4), 4);
ExpectIntLE(test_ctx.s_len, sizeof(readBuf));
ExpectIntGT(test_ctx.s_len, 10);
record_len = test_ctx.s_len;
if (EXPECT_SUCCESS())
XMEMCPY(readBuf, test_ctx.s_buff, record_len);
/* drop record and simulate a split write */
ExpectIntEQ(test_memio_drop_message(&test_ctx, 0, 0), 0);
ExpectIntEQ(test_ctx.s_msg_count, 0);
/* inject first record header */
ExpectIntEQ(
test_memio_inject_message(&test_ctx, 0, (const char*)readBuf, 5), 0);
ExpectIntEQ(test_ctx.s_msg_count, 1);
ExpectIntEQ(test_ctx.s_msg_sizes[0], 5);
/* inject another 5 bytes of the record */
ExpectIntEQ(
test_memio_inject_message(&test_ctx, 0, (const char*)readBuf + 5, 5),
0);
ExpectIntEQ(test_ctx.s_msg_count, 2);
ExpectIntEQ(test_ctx.s_msg_sizes[1], 5);
/* inject the rest of the record */
ExpectIntEQ(test_memio_inject_message(&test_ctx, 0,
(const char*)readBuf + 10, record_len - 10),
0);
ExpectIntEQ(test_ctx.s_msg_count, 3);
ExpectIntEQ(test_ctx.s_msg_sizes[2], record_len - 10);
/* read the record */
wolfSSL_SetLoggingPrefix("server");
ExpectIntEQ(wolfSSL_read(ssl_s, readBuf, sizeof(readBuf)), 4);
ExpectIntEQ(test_ctx.s_len, 0);
ExpectBufEQ(readBuf, "test", 4);
wolfSSL_free(ssl_s);
wolfSSL_free(ssl_c);
wolfSSL_CTX_free(ctx_s);
wolfSSL_CTX_free(ctx_c);
return EXPECT_RESULT();
}
#else
int test_records_span_network_boundaries(void)
{
return TEST_SKIPPED;
}
#endif /* defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \
!defined(WOLFSSL_NO_TLS12) */
int test_dtls_mtu_fragment_headroom(void)
{
#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \
defined(WOLFSSL_DTLS_MTU) && defined(HAVE_AESGCM) && defined(HAVE_ECC) && \
!defined(WOLFSSL_NO_DTLS_SIZE_CHECK)
EXPECT_DECLS;
struct {
method_provider client_meth;
method_provider server_meth;
const char* cipher;
int use_cid;
} params[] = {
#if defined(WOLFSSL_DTLS13) && defined(WOLFSSL_TLS13)
{ wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method,
"TLS13-AES128-GCM-SHA256", 0 },
#ifdef WOLFSSL_DTLS_CID
{ wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method,
"TLS13-AES128-GCM-SHA256", 1 },
#endif
#endif
#if defined(WOLFSSL_DTLS) && !defined(WOLFSSL_NO_TLS12)
{ wolfDTLSv1_2_client_method, wolfDTLSv1_2_server_method,
"ECDHE-RSA-AES128-GCM-SHA256", 0 },
#ifdef WOLFSSL_DTLS_CID
{ wolfDTLSv1_2_client_method, wolfDTLSv1_2_server_method,
"ECDHE-RSA-AES128-GCM-SHA256", 1 },
#endif
#if !defined(WOLFSSL_AEAD_ONLY) && !defined(NO_AES) && !defined(NO_SHA)
{ wolfDTLSv1_2_client_method, wolfDTLSv1_2_server_method,
"ECDHE-RSA-AES128-SHA", 0 },
#ifdef WOLFSSL_DTLS_CID
{ wolfDTLSv1_2_client_method, wolfDTLSv1_2_server_method,
"ECDHE-RSA-AES128-SHA", 1 },
#endif
#endif
#endif
};
size_t i;
for (i = 0; i < XELEM_CNT(params) && EXPECT_SUCCESS(); i++) {
WOLFSSL_CTX *ctx_c = NULL, *ctx_s = NULL;
WOLFSSL *ssl_c = NULL, *ssl_s = NULL;
struct test_memio_ctx test_ctx;
unsigned char payload[33];
word16 mtu;
int recordLen;
int overhead;
int ret;
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
XMEMSET(payload, 'A', sizeof(payload));
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
params[i].client_meth, params[i].server_meth),
0);
ExpectIntEQ(wolfSSL_set_cipher_list(ssl_c, params[i].cipher), 1);
ExpectIntEQ(wolfSSL_set_cipher_list(ssl_s, params[i].cipher), 1);
#ifdef WOLFSSL_DTLS_CID
if (params[i].use_cid) {
unsigned char cid_c[] = { 0,1,2,3 };
unsigned char cid_s[] = { 4,5,6,7,8,9 };
ExpectIntEQ(wolfSSL_dtls_cid_use(ssl_c), 1);
ExpectIntEQ(wolfSSL_dtls_cid_use(ssl_s), 1);
ExpectIntEQ(wolfSSL_dtls_cid_set(ssl_c, cid_s, (int)sizeof(cid_s)),
1);
ExpectIntEQ(wolfSSL_dtls_cid_set(ssl_s, cid_c, (int)sizeof(cid_c)),
1);
}
#endif
/* Complete handshake and clear any leftover records. */
ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0);
test_memio_clear_buffer(&test_ctx, 1);
test_memio_clear_buffer(&test_ctx, 0);
/* Measure application-data record overhead. */
ExpectIntEQ(wolfSSL_write(ssl_c, payload, 32), 32);
ExpectIntEQ(test_ctx.s_msg_count, 1);
recordLen = test_ctx.s_len;
ExpectIntGT(recordLen, 32);
overhead = recordLen - 32;
/* Reset buffers before MTU-limited send. */
test_memio_clear_buffer(&test_ctx, 0);
test_memio_clear_buffer(&test_ctx, 1);
/* Set MTU to overhead + 32 bytes of payload. */
mtu = (word16)(overhead + 32);
ExpectIntEQ(wolfSSL_dtls_set_mtu(ssl_c, mtu), WOLFSSL_SUCCESS);
ExpectIntEQ(wolfSSL_dtls_set_mtu(ssl_s, mtu), WOLFSSL_SUCCESS);
/* With the tightened MTU, we should still be able to send 32 bytes. */
ExpectIntEQ(wolfSSL_write(ssl_c, payload, 32), 32);
ExpectIntEQ(test_ctx.s_msg_count, 1);
recordLen = test_ctx.s_len;
ExpectIntEQ(recordLen, overhead + 32);
ExpectIntLE(recordLen, mtu);
/* Underestimation: drop MTU by 1 and expect DTLS_SIZE_ERROR. */
test_memio_clear_buffer(&test_ctx, 0);
test_memio_clear_buffer(&test_ctx, 1);
ExpectIntEQ(wolfSSL_dtls_set_mtu(ssl_c, mtu - 1), WOLFSSL_SUCCESS);
ret = wolfSSL_write(ssl_c, payload, 32);
ExpectIntNE(ret, 32);
ExpectIntEQ(wolfSSL_get_error(ssl_c, ret), DTLS_SIZE_ERROR);
wolfSSL_free(ssl_c);
wolfSSL_CTX_free(ctx_c);
wolfSSL_free(ssl_s);
wolfSSL_CTX_free(ctx_s);
}
return EXPECT_RESULT();
#else
return TEST_SKIPPED;
#endif
}
int test_dtls_rtx_across_epoch_change(void)
{
EXPECT_DECLS;
#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \
defined(WOLFSSL_DTLS13) && defined(WOLFSSL_DTLS)
WOLFSSL_CTX *ctx_c = NULL, *ctx_s = NULL;
WOLFSSL *ssl_c = NULL, *ssl_s = NULL;
struct test_memio_ctx test_ctx;
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
/* Setup DTLS contexts */
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method),
0);
/* CH0 */
wolfSSL_SetLoggingPrefix("client:");
ExpectIntEQ(wolfSSL_connect(ssl_c), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), SSL_ERROR_WANT_READ);
/* HRR */
wolfSSL_SetLoggingPrefix("server:");
ExpectIntEQ(wolfSSL_accept(ssl_s), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), SSL_ERROR_WANT_READ);
/* CH1 */
wolfSSL_SetLoggingPrefix("client:");
ExpectIntEQ(wolfSSL_connect(ssl_c), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), SSL_ERROR_WANT_READ);
/* SH ... FINISHED */
wolfSSL_SetLoggingPrefix("server:");
ExpectIntEQ(wolfSSL_accept(ssl_s), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), SSL_ERROR_WANT_READ);
/* we should have now SH ... FINISHED messages in the buffer*/
ExpectIntGE(test_ctx.c_msg_count, 2);
/* drop everything but the SH */
while (test_ctx.c_msg_count > 1 && EXPECT_SUCCESS()) {
ExpectIntEQ(test_memio_drop_message(&test_ctx, 1, test_ctx.c_msg_count - 1), 0);
}
/* Read the SH */
wolfSSL_SetLoggingPrefix("client:");
ExpectIntEQ(wolfSSL_connect(ssl_c), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), SSL_ERROR_WANT_READ);
/* trigger client timeout */
ExpectIntEQ(wolfSSL_dtls_got_timeout(ssl_c), WOLFSSL_SUCCESS);
/* this should have triggered a rtx */
ExpectIntGT(test_ctx.s_msg_count, 0);
/* finish the handshake */
ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0);
/* Test communication works correctly */
ExpectIntEQ(test_dtls_communication(ssl_s, ssl_c), TEST_SUCCESS);
/* Cleanup */
wolfSSL_free(ssl_c);
wolfSSL_CTX_free(ctx_c);
wolfSSL_free(ssl_s);
wolfSSL_CTX_free(ctx_s);
#endif /* defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \
defined(WOLFSSL_DTLS13) */
return EXPECT_RESULT();
}
int test_dtls_drop_client_ack(void)
{
EXPECT_DECLS;
#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \
defined(WOLFSSL_DTLS13) && defined(WOLFSSL_DTLS)
WOLFSSL_CTX *ctx_c = NULL, *ctx_s = NULL;
WOLFSSL *ssl_c = NULL, *ssl_s = NULL;
struct test_memio_ctx test_ctx;
char data[32];
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
/* Setup DTLS contexts */
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method),
0);
/* disable new session ticket to simplify testing */
ExpectIntEQ(wolfSSL_no_ticket_TLSv13(ssl_s), 0);
/* CH0 */
wolfSSL_SetLoggingPrefix("client:");
ExpectIntEQ(wolfSSL_connect(ssl_c), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
/* HRR */
wolfSSL_SetLoggingPrefix("server:");
ExpectIntEQ(wolfSSL_accept(ssl_s), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ);
/* CH1 */
wolfSSL_SetLoggingPrefix("client:");
ExpectIntEQ(wolfSSL_connect(ssl_c), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
/* SH ... FINISHED */
wolfSSL_SetLoggingPrefix("server:");
ExpectIntEQ(wolfSSL_accept(ssl_s), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ);
/* ... FINISHED */
wolfSSL_SetLoggingPrefix("client:");
ExpectIntEQ(wolfSSL_connect(ssl_c), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
/* init is finished should return false at this point */
ExpectFalse(wolfSSL_is_init_finished(ssl_c));
/* ACK */
ExpectIntEQ(wolfSSL_accept(ssl_s), WOLFSSL_SUCCESS);
/* Drop the ack */
test_memio_clear_buffer(&test_ctx, 1);
/* trigger client timeout, finished should be rtx */
ExpectIntEQ(wolfSSL_dtls_got_timeout(ssl_c), WOLFSSL_SUCCESS);
ExpectIntEQ(wolfSSL_dtls_got_timeout(ssl_c), WOLFSSL_SUCCESS);
/* this should have triggered a rtx */
ExpectIntGT(test_ctx.s_msg_count, 0);
/* this should re-send the ack immediately */
ExpectIntEQ(wolfSSL_read(ssl_s, data, 32), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ);
ExpectIntEQ(test_ctx.c_msg_count, 1);
/* This should advance the connection on the client */
ExpectIntEQ(wolfSSL_negotiate(ssl_c), WOLFSSL_SUCCESS);
/* Test communication works correctly */
ExpectIntEQ(test_dtls_communication(ssl_s, ssl_c), TEST_SUCCESS);
/* Cleanup */
wolfSSL_free(ssl_c);
wolfSSL_CTX_free(ctx_c);
wolfSSL_free(ssl_s);
wolfSSL_CTX_free(ctx_s);
#endif /* defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \
defined(WOLFSSL_DTLS13) */
return EXPECT_RESULT();
}
int test_dtls_bogus_finished_epoch_zero(void)
{
EXPECT_DECLS;
#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_DTLS) && \
!defined(WOLFSSL_NO_TLS12) && defined(HAVE_AES_CBC) && \
defined(WOLFSSL_AES_128) && !defined(NO_SHA256)
WOLFSSL_CTX *ctx_c = NULL, *ctx_s = NULL;
WOLFSSL *ssl_c = NULL, *ssl_s = NULL;
struct test_memio_ctx test_ctx;
int error;
/* bogus Finished message bytes from the original bug report (epoch 0)
* https://github.com/wolfSSL/wolfssl/issues/9188 */
static const unsigned char bogus_finished[] = {
0x16, 0xfe, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x18, 0x14, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x0c, 0xd9, 0xc6, 0xe3, 0x01, 0x59, 0xf2, 0xc2, 0x4f, 0xfa, 0xfd, 0x20,
0xd7
};
/* serverHelloDone message bytes */
static const unsigned char server_hello_done_message[] = {
0x16, 0xfe, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
0x0c, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00
};
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
/* setting up dtls 1.2 contexts */
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
wolfDTLSv1_2_client_method, wolfDTLSv1_2_server_method), 0);
/* start handshake, send first ClientHelloDone */
ExpectIntEQ(wolfSSL_connect(ssl_c), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
/* clearing server buffer to inject the wrong Finished packet */
test_memio_clear_buffer(&test_ctx, 1);
ExpectIntEQ(test_memio_inject_message(&test_ctx, 1,
(const char*)bogus_finished, sizeof(bogus_finished)), 0);
/* continue client handshake to process it */
ExpectIntEQ(wolfSSL_connect(ssl_c), -1);
/* client should terminate with dtls sequence error */
error = wolfSSL_get_error(ssl_c, -1);
/* check if the error is SEQUENCE_ERROR, handshake should not
* expect a finished packet in that moment, in particular should not
* be in epoch = 0 (should be epoch = 1) */
ExpectTrue(error == WC_NO_ERR_TRACE(SEQUENCE_ERROR) ||
error == WC_NO_ERR_TRACE(WOLFSSL_ERROR_WANT_READ));
/* forcing injection ServerHelloDone to test if client would replay
* ClientHello */
test_memio_clear_buffer(&test_ctx, 0);
ExpectIntEQ(test_memio_inject_message(&test_ctx, 1,
(const char*)server_hello_done_message, sizeof(server_hello_done_message)), 0);
ExpectIntEQ(wolfSSL_connect(ssl_c), -1);
/* verifying no ClientHello replay occurred,
* buffer should empty since we exit early on
* because of the bogus finished packet */
ExpectIntLE(test_ctx.s_len, 0);
wolfSSL_free(ssl_c);
wolfSSL_CTX_free(ctx_c);
wolfSSL_free(ssl_s);
wolfSSL_CTX_free(ctx_s);
#endif
return EXPECT_RESULT();
}
int test_dtls_replay(void)
{
EXPECT_DECLS;
#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_DTLS)
size_t i;
struct {
method_provider client_meth;
method_provider server_meth;
const char* tls_version;
} params[] = {
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_DTLS13)
{ wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method, "DTLSv1_3" },
#endif
#if !defined(WOLFSSL_NO_TLS12) && defined(WOLFSSL_DTLS)
{ wolfDTLSv1_2_client_method, wolfDTLSv1_2_server_method, "DTLSv1_2" },
#endif
#if !defined(NO_OLD_TLS) && defined(WOLFSSL_DTLS)
{ wolfDTLSv1_client_method, wolfDTLSv1_server_method, "DTLSv1_0" },
#endif
};
for (i = 0; i < XELEM_CNT(params) && !EXPECT_FAIL(); i++) {
WOLFSSL_CTX *ctx_c = NULL, *ctx_s = NULL;
WOLFSSL *ssl_c = NULL, *ssl_s = NULL;
struct test_memio_ctx test_ctx;
char msg_buf[256];
int msg_len = sizeof(msg_buf);
byte app_data[8];
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
/* Setup DTLS contexts */
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
params[i].client_meth, params[i].server_meth), 0);
ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0);
ExpectIntEQ(wolfSSL_write(ssl_c, "test", 4), 4);
ExpectIntEQ(test_memio_copy_message(&test_ctx, 0, msg_buf, &msg_len, 0), 0);
ExpectIntEQ(wolfSSL_read(ssl_s, app_data, sizeof(app_data)), 4);
ExpectIntEQ(test_memio_inject_message(&test_ctx, 0, msg_buf, msg_len), 0);
ExpectIntEQ(wolfSSL_read(ssl_s, app_data, sizeof(app_data)), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ);
wolfSSL_free(ssl_c);
wolfSSL_CTX_free(ctx_c);
wolfSSL_free(ssl_s);
wolfSSL_CTX_free(ctx_s);
}
#endif
return EXPECT_RESULT();
}
#if defined(WOLFSSL_DTLS13) && defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES) && \
defined(WOLFSSL_SRTP)
static int test_dtls_srtp_ctx_ready(WOLFSSL_CTX* ctx)
{
EXPECT_DECLS;
ExpectIntEQ(wolfSSL_CTX_set_tlsext_use_srtp(ctx, "SRTP_AEAD_AES_256_GCM:"
"SRTP_AEAD_AES_128_GCM:SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32"),
0);
return EXPECT_RESULT();
}
int test_dtls_srtp(void)
{
EXPECT_DECLS;
test_ssl_cbf client_cbf;
test_ssl_cbf server_cbf;
XMEMSET(&client_cbf, 0, sizeof(client_cbf));
XMEMSET(&server_cbf, 0, sizeof(server_cbf));
client_cbf.method = wolfDTLSv1_3_client_method;
client_cbf.ctx_ready = test_dtls_srtp_ctx_ready;
server_cbf.method = wolfDTLSv1_3_server_method;
server_cbf.ctx_ready = test_dtls_srtp_ctx_ready;
ExpectIntEQ(test_wolfSSL_client_server_nofail_memio(&client_cbf,
&server_cbf, NULL), TEST_SUCCESS);
return EXPECT_RESULT();
}
#else
int test_dtls_srtp(void)
{
EXPECT_DECLS;
return EXPECT_RESULT();
}
#endif
int test_dtls_timeout(void)
{
EXPECT_DECLS;
#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_DTLS)
size_t i;
struct {
method_provider client_meth;
method_provider server_meth;
} params[] = {
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_DTLS13)
{ wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method },
#endif
#if !defined(WOLFSSL_NO_TLS12) && defined(WOLFSSL_DTLS)
{ wolfDTLSv1_2_client_method, wolfDTLSv1_2_server_method },
#endif
#if !defined(NO_OLD_TLS) && defined(WOLFSSL_DTLS)
{ wolfDTLSv1_client_method, wolfDTLSv1_server_method },
#endif
};
for (i = 0; i < XELEM_CNT(params) && !EXPECT_FAIL(); i++) {
WOLFSSL_CTX *ctx_c = NULL, *ctx_s = NULL;
WOLFSSL *ssl_c = NULL, *ssl_s = NULL;
struct test_memio_ctx test_ctx;
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
params[i].client_meth, params[i].server_meth), 0);
ExpectIntEQ(wolfSSL_dtls_set_timeout_max(ssl_c, 2), WOLFSSL_SUCCESS);
ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_DTLS13)
/* will return 0 when not 1.3 */
if (wolfSSL_dtls13_use_quick_timeout(ssl_c))
ExpectIntEQ(wolfSSL_dtls_got_timeout(ssl_c), WOLFSSL_SUCCESS);
#endif
ExpectIntEQ(wolfSSL_dtls_got_timeout(ssl_c), WOLFSSL_SUCCESS);
ExpectIntEQ(wolfSSL_dtls_get_current_timeout(ssl_c), 2);
ExpectIntEQ(wolfSSL_negotiate(ssl_s), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ);
ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
ExpectIntEQ(wolfSSL_dtls_get_current_timeout(ssl_c), 1);
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_DTLS13)
/* will return 0 when not 1.3 */
if (wolfSSL_dtls13_use_quick_timeout(ssl_c))
ExpectIntEQ(wolfSSL_dtls_got_timeout(ssl_c), WOLFSSL_SUCCESS);
#endif
ExpectIntEQ(wolfSSL_dtls_got_timeout(ssl_c), WOLFSSL_SUCCESS);
ExpectIntEQ(wolfSSL_dtls_get_current_timeout(ssl_c), 2);
ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0);
wolfSSL_free(ssl_s);
wolfSSL_free(ssl_c);
wolfSSL_CTX_free(ctx_s);
wolfSSL_CTX_free(ctx_c);
}
#endif
return EXPECT_RESULT();
}
int test_dtls_certreq_order(void)
{
EXPECT_DECLS;
#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_DTLS) && \
!defined(WOLFSSL_NO_TLS12) && defined(HAVE_AESGCM) && \
defined(WOLFSSL_AES_128) && !defined(NO_SHA256) && !defined(NO_RSA) && \
!defined(NO_DH)
/* This test checks that a certificate request message
* received before server certificate message is properly detected.
* The binary is taken from https://github.com/wolfSSL/wolfssl/issues/9198
*/
static const unsigned char certreq_before_cert_bin[] = {
0x16, 0xfe, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x39, 0x02, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x2d, 0xfe, 0xfd, 0x48, 0xc0, 0xd5, 0xf2, 0x60, 0xb4, 0x20, 0xbb, 0x38,
0x51, 0xd9, 0xd4, 0x7a, 0xcb, 0x93, 0x3d, 0xbe, 0x70, 0x39, 0x9b, 0xf6,
0xc9, 0x2d, 0xa3, 0x3a, 0xf0, 0x1d, 0x4f, 0xb7, 0x70, 0xe9, 0x8c, 0x00,
0x00, 0x9e, 0x00, 0x00, 0x05, 0x00, 0x0f, 0x00, 0x01, 0x01, 0x16, 0xfe,
0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x3a, 0x0d,
0x00, 0x00, 0x2e, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x01,
0x01, 0x00, 0x28, 0x02, 0x02, 0x03, 0x02, 0x04, 0x02, 0x05, 0x02, 0x06,
0x02, 0x01, 0x01, 0x02, 0x01, 0x03, 0x01, 0x04, 0x01, 0x05, 0x01, 0x06,
0x01, 0x02, 0x03, 0x03, 0x03, 0x04, 0x03, 0x05, 0x03, 0x06, 0x03, 0x08,
0x04, 0x08, 0x05, 0x08, 0x06, 0x07, 0x08, 0x00, 0x00, 0x16, 0xfe, 0xfd,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x2b, 0x0b, 0x00,
0x03, 0x1f, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x03, 0x1f, 0x00, 0x03,
0x1c, 0x00, 0x03, 0x19, 0x30, 0x82, 0x03, 0x15, 0x30, 0x82, 0x01, 0xfd,
0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x14, 0x40, 0xe7, 0x6e, 0x85, 0x66,
0x7c, 0x3f, 0x04, 0x87, 0x4c, 0x3f, 0x94, 0x21, 0x6d, 0x21, 0x65, 0xa5,
0x28, 0xa7, 0x38, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x1a, 0x31, 0x18, 0x30, 0x16,
0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0f, 0x64, 0x74, 0x6c, 0x73, 0x2d,
0x66, 0x75, 0x7a, 0x7a, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x1e,
0x17, 0x0d, 0x32, 0x34, 0x30, 0x36, 0x30, 0x36, 0x31, 0x32, 0x31, 0x33,
0x30, 0x33, 0x5a, 0x17, 0x0d, 0x33, 0x38, 0x30, 0x32, 0x31, 0x33, 0x31,
0x32, 0x31, 0x33, 0x30, 0x33, 0x5a, 0x30, 0x1a, 0x31, 0x18, 0x30, 0x16,
0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0f, 0x64, 0x74, 0x6c, 0x73, 0x2d,
0x66, 0x75, 0x7a, 0x7a, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x82,
0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82,
0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xbb, 0x2a, 0x06, 0xfa, 0xaf,
0x9c, 0xb7, 0xeb, 0x33, 0xce, 0xde, 0xf6, 0xb6, 0x0a, 0x93, 0xb3, 0x97,
0x7a, 0x36, 0x55, 0x89, 0xc2, 0xf5, 0x45, 0x84, 0x6d, 0x45, 0x25, 0x5c,
0x4f, 0xa8, 0x8a, 0x41, 0x29, 0x5b, 0x71, 0x98, 0x6c, 0x63, 0xe7, 0xcf,
0x7f, 0xb4, 0x9d, 0x06, 0x76, 0x60, 0x8c, 0x6a, 0x26, 0x47, 0x65, 0x5d,
0x74, 0x7a, 0xb5, 0x40, 0x33, 0x61, 0xe0, 0x28, 0xed, 0xa6, 0x66, 0x6a,
0x4b, 0x97, 0xaf, 0xae, 0x6c, 0xa1, 0xf2, 0xfc, 0xd0, 0xf1, 0x61, 0x98,
0x05, 0x2a, 0x02, 0x42, 0x13, 0x06, 0x7c, 0x4a, 0x7e, 0x53, 0x01, 0x87,
0x27, 0x6c, 0x41, 0xe8, 0xed, 0x6e, 0xb2, 0x45, 0x90, 0xe8, 0x93, 0xc0,
0x20, 0xff, 0x64, 0xdf, 0x48, 0x57, 0xb9, 0x62, 0x8c, 0x14, 0x88, 0xc9,
0x4a, 0x56, 0x3f, 0x5d, 0x9f, 0xeb, 0x1d, 0x79, 0x75, 0xfd, 0x24, 0xad,
0xb6, 0x65, 0x1d, 0x53, 0x81, 0x5c, 0x67, 0xbe, 0x3a, 0x9d, 0xcd, 0xe1,
0x47, 0xab, 0x8d, 0xd4, 0xa5, 0xbd, 0xa6, 0xd7, 0x60, 0xf9, 0x5c, 0x32,
0x51, 0x65, 0x7e, 0x8b, 0xd6, 0xa1, 0x5b, 0xa2, 0xf5, 0x60, 0xaf, 0x29,
0xff, 0x9f, 0x3a, 0xa4, 0xd0, 0x5d, 0x6e, 0x96, 0x09, 0xe8, 0xcf, 0xc3,
0xe1, 0xe8, 0x5a, 0x82, 0xce, 0x9a, 0x3c, 0xc6, 0xbb, 0xe5, 0x4c, 0xa8,
0xa4, 0xb0, 0xfd, 0x86, 0x06, 0x8b, 0x3f, 0x7e, 0x38, 0xe4, 0x06, 0xdf,
0xf7, 0x9c, 0xc6, 0x8b, 0x1d, 0xb5, 0xad, 0x7a, 0x91, 0x5f, 0x64, 0xa5,
0x69, 0xc8, 0x7b, 0x77, 0x32, 0x71, 0x8f, 0x73, 0x82, 0xd2, 0x21, 0xe8,
0xa8, 0x81, 0xfe, 0x76, 0x7f, 0x20, 0xd1, 0xb6, 0x42, 0x9e, 0xaf, 0x60,
0x85, 0x47, 0xf5, 0xfe, 0x9f, 0x85, 0xbf, 0xb0, 0x11, 0xb7, 0xf7, 0x83,
0x0d, 0x80, 0x63, 0xa0, 0xf7, 0x0c, 0x2c, 0x83, 0x12, 0xa9, 0x0f, 0x02,
0x03, 0x01, 0x00, 0x01, 0xa3, 0x53, 0x30, 0x51, 0x30, 0x1d, 0x06, 0x03,
0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x2a, 0xb5, 0x00, 0x45, 0x06,
0x08, 0xef, 0xe5, 0xfa, 0x78, 0x19, 0x47, 0x5b, 0x04, 0x40, 0x18, 0xf3,
0xeb, 0xab, 0x99, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18,
0x30, 0x16, 0x80, 0x14, 0x2a, 0xb5, 0x00, 0x45, 0x06, 0x08, 0xef, 0xe5,
0xfa, 0x78, 0x19, 0x47, 0x5b, 0x04, 0x40, 0x18, 0xf3, 0xeb, 0xab, 0x99,
0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05,
0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48,
0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01,
0x00, 0xa7, 0x58, 0x65, 0xfc, 0x60, 0x3e, 0xb7, 0x34, 0x82, 0xde, 0x04,
0x06, 0x3d, 0x69, 0x62, 0x8a, 0x4c, 0xcc, 0xd6, 0x54, 0x72, 0x81, 0xcb,
0x31, 0xdf, 0x63, 0xaf, 0x84, 0x27, 0x62, 0xbf, 0xe8, 0x6b, 0xf9, 0x81,
0xd4, 0x5a, 0x98, 0x88, 0xae, 0x05, 0x5b, 0x2c, 0xa3, 0xf8, 0xb0, 0xde,
0x9b, 0x44, 0xc7, 0x1d, 0x19, 0x52, 0x02, 0x02, 0xd9, 0x0e, 0x66, 0x7b,
0x25, 0xdf, 0x95, 0x03, 0x5e, 0x4b, 0x15, 0xef, 0xda, 0x86, 0x2e, 0x8b,
0xc4, 0xe7, 0x2d, 0x3f, 0x5f, 0xea, 0x1f, 0x13, 0x81, 0x2e, 0x6e, 0xf8,
0x7f, 0x0b, 0x3b, 0x95, 0x4f, 0xb6, 0xb3, 0x91, 0xcf, 0x89, 0x52, 0xdb,
0xb7, 0xb1, 0x5d, 0x79, 0xdf, 0x3a, 0xf3, 0xe2, 0x46, 0xc4, 0x04, 0xf3,
0xf4, 0xf1, 0xc3, 0xf3, 0xa4, 0x98, 0x47, 0xae, 0x46, 0x99, 0x43, 0x4b,
0x20, 0xba, 0x33, 0xaa, 0x7e, 0x2e, 0x80, 0x88, 0x25, 0x84, 0x73, 0x6d,
0x44, 0x5f, 0x48, 0x57, 0x0a, 0xc4, 0x4a, 0x4d, 0xc4, 0xd1, 0x47, 0x5f,
0x4f, 0xd5, 0xdb, 0x3e, 0x90, 0xbd, 0xe1, 0x6a, 0xcb, 0xe4, 0xf3, 0xe6,
0x64, 0x26, 0xbd, 0xb6, 0x0b, 0x95, 0x6f, 0x4e, 0x1b, 0x09, 0x25, 0x68,
0x93, 0xb6, 0xd0, 0xc2, 0xfc, 0xce, 0x8f, 0x64, 0xf5, 0x75, 0x50, 0x58,
0xe5, 0x3e, 0x00, 0x01, 0xfd, 0x62, 0x37, 0xe1, 0x37, 0x1e, 0x9f, 0x97,
0x88, 0xb1, 0xa9, 0x6f, 0xad, 0x93, 0x41, 0x01, 0xfb, 0x38, 0x24, 0xc8,
0x08, 0xa0, 0x68, 0x4b, 0x34, 0x8b, 0x76, 0xea, 0x01, 0x62, 0x9d, 0xfa,
0xdc, 0x91, 0x50, 0x47, 0x98, 0xec, 0x0c, 0x44, 0x58, 0xb6, 0x16, 0xa0,
0x05, 0xf2, 0x94, 0x34, 0x6d, 0xcb, 0xbc, 0xe4, 0x58, 0xd6, 0x97, 0x9d,
0x57, 0xa5, 0x5a, 0x65, 0xfa, 0xab, 0x94, 0x24, 0xbf, 0x06, 0x64, 0xc0,
0xe5, 0x89, 0xe4, 0x2e, 0x46, 0x16, 0xfe, 0xfd, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x03, 0x03, 0x17, 0x0c, 0x00, 0x03, 0x0b, 0x00, 0x03,
0x00, 0x00, 0x00, 0x00, 0x03, 0x0b, 0x01, 0x00, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xad, 0xf8, 0x54, 0x58, 0xa2, 0xbb, 0x4a, 0x9a,
0xaf, 0xdc, 0x56, 0x20, 0x27, 0x3d, 0x3c, 0xf1, 0xd8, 0xb9, 0xc5, 0x83,
0xce, 0x2d, 0x36, 0x95, 0xa9, 0xe1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xfb,
0xcc, 0x93, 0x9d, 0xce, 0x24, 0x9b, 0x3e, 0xf9, 0x7d, 0x2f, 0xe3, 0x63,
0x63, 0x0c, 0x75, 0xd8, 0xf6, 0x81, 0xb2, 0x02, 0xae, 0xc4, 0x61, 0x7a,
0xd3, 0xdf, 0x1e, 0xd5, 0xd5, 0xfd, 0x65, 0x61, 0x24, 0x33, 0xf5, 0x1f,
0x5f, 0x06, 0x6e, 0xd0, 0x85, 0x63, 0x65, 0x55, 0x3d, 0xed, 0x1a, 0xf3,
0xb5, 0x57, 0x13, 0x5e, 0x7f, 0x57, 0xc9, 0x35, 0x98, 0x4f, 0x0c, 0x70,
0xe0, 0xe6, 0x8b, 0x77, 0xe2, 0xa6, 0x89, 0xda, 0xf3, 0xef, 0xe8, 0x72,
0x1d, 0xf1, 0x58, 0xa1, 0x36, 0xad, 0xe7, 0x35, 0x30, 0xac, 0xca, 0x4f,
0x48, 0x3a, 0x79, 0x7a, 0xbc, 0x0a, 0xb1, 0x82, 0xb3, 0x24, 0xfb, 0x61,
0xd1, 0x08, 0xa9, 0x4b, 0xb2, 0xc8, 0xe3, 0xfb, 0xb9, 0x6a, 0xda, 0xb7,
0x60, 0xd7, 0xf4, 0x68, 0x1d, 0x4f, 0x42, 0xa3, 0xde, 0x39, 0x4d, 0xf4,
0xae, 0x56, 0xed, 0xe7, 0x63, 0x72, 0xbb, 0x19, 0x0b, 0x07, 0xa7, 0xc8,
0xee, 0x0a, 0x6d, 0x70, 0x9e, 0x02, 0xfc, 0xe1, 0xcd, 0xf7, 0xe2, 0xec,
0xc0, 0x34, 0x04, 0xcd, 0x28, 0x34, 0x2f, 0x61, 0x91, 0x72, 0xfe, 0x9c,
0xe9, 0x85, 0x83, 0xff, 0x8e, 0x4f, 0x12, 0x32, 0xee, 0xf2, 0x81, 0x83,
0xc3, 0xfe, 0x3b, 0x1b, 0x4c, 0x6f, 0xad, 0x73, 0x3b, 0xb5, 0xfc, 0xbc,
0x2e, 0xc2, 0x20, 0x05, 0xc5, 0x8e, 0xf1, 0x83, 0x7d, 0x16, 0x83, 0xb2,
0xc6, 0xf3, 0x4a, 0x26, 0xc1, 0xb2, 0xef, 0xfa, 0x88, 0x6b, 0x42, 0x38,
0x61, 0x28, 0x5c, 0x97, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x00, 0x01, 0x02, 0x01, 0x00, 0xea, 0x10, 0x0e, 0xb8, 0xc4, 0xc9, 0xc9,
0x9a, 0x8c, 0x03, 0x04, 0x56, 0x4f, 0x3d, 0x2d, 0x64, 0x51, 0xc9, 0x1e,
0xf7, 0x63, 0x06, 0x81, 0xca, 0x89, 0x5c, 0x81, 0xb9, 0x78, 0xe0, 0xf5,
0x43, 0xe4, 0x47, 0x40, 0x8f, 0x0e, 0xab, 0x0e, 0xd0, 0xb4, 0x43, 0x92,
0x2a, 0x03, 0x4a, 0x1f, 0x69, 0x7b, 0xc3, 0x0c, 0x13, 0x0d, 0xf3, 0xd8,
0xaa, 0xd7, 0x1e, 0x0e, 0xf5, 0x09, 0x7d, 0xda, 0xc9, 0x7c, 0x16, 0xfd,
0xe6, 0xbb, 0x2d, 0xc1, 0x12, 0x20, 0xad, 0x8f, 0x1b, 0x64, 0x79, 0xb9,
0xbc, 0x26, 0x11, 0xec, 0x3d, 0x20, 0xa6, 0x18, 0x6c, 0xb3, 0x27, 0xbe,
0x86, 0xde, 0x0e, 0x49, 0x8f, 0xc2, 0x0e, 0x86, 0x8b, 0x2a, 0xc7, 0x4c,
0xb5, 0x09, 0xed, 0x94, 0x6d, 0xb6, 0x50, 0xfb, 0xc1, 0x8e, 0xd7, 0xce,
0x58, 0xf8, 0xb0, 0x68, 0xbc, 0xcf, 0x28, 0xc5, 0x1c, 0xf3, 0x99, 0x17,
0x22, 0xaa, 0x40, 0x28, 0x90, 0x78, 0x34, 0xe2, 0x0f, 0x28, 0x0d, 0x22,
0xe1, 0x55, 0xcd, 0x90, 0x26, 0x84, 0xa0, 0xd8, 0xea, 0xd9, 0xe8, 0x83,
0x43, 0x24, 0xef, 0x66, 0xa6, 0x7f, 0x9f, 0x56, 0x10, 0x6f, 0xc9, 0x13,
0x2f, 0xb1, 0x00, 0x49, 0xc7, 0x88, 0x8d, 0xec, 0x55, 0xc1, 0xdb, 0x39,
0xa2, 0x5e, 0xbd, 0xde, 0xb6, 0x0a, 0x1c, 0x1f, 0xa4, 0x1a, 0x93, 0xc2,
0xee, 0x9c, 0x63, 0x3b, 0x09, 0xcf, 0xf6, 0x93, 0x83, 0xfe, 0xd7, 0x4d,
0x35, 0xd3, 0x15, 0x74, 0x23, 0x5a, 0x33, 0xdc, 0x64, 0x9d, 0xba, 0x2a,
0xb0, 0x63, 0x26, 0x17, 0x44, 0xe2, 0xfa, 0x41, 0xb1, 0xb2, 0xf2, 0x63,
0xb2, 0x51, 0x50, 0xfc, 0x31, 0xc2, 0xd6, 0xda, 0x01, 0x18, 0xcf, 0xe8,
0x9b, 0xed, 0x4c, 0x69, 0x38, 0xe1, 0xe2, 0x69, 0x53, 0xdc, 0x85, 0x40,
0x4e, 0x9a, 0x1d, 0xe8, 0x2a, 0xe1, 0x27, 0xad, 0x8e, 0x03, 0x01, 0x01,
0x00, 0xad, 0x55, 0xc0, 0xac, 0xbb, 0x32, 0x93, 0x86, 0xc6, 0xdf, 0x5d,
0x58, 0x94, 0xba, 0x35, 0x81, 0x32, 0x54, 0x98, 0xdc, 0x85, 0x6f, 0x1e,
0x41, 0xe4, 0x3d, 0x1e, 0x0d, 0x37, 0x85, 0x05, 0xd1, 0xf7, 0xb2, 0x3a,
0xd5, 0xb1, 0x8c, 0x93, 0x20, 0x8a, 0x42, 0xf0, 0xc9, 0x86, 0xcc, 0xf4,
0xa1, 0x17, 0x8d, 0x65, 0xd0, 0xea, 0x23, 0x9f, 0xf7, 0xcf, 0x3e, 0x7b,
0x51, 0x55, 0xfe, 0x3d, 0x6c, 0x9e, 0x3e, 0x51, 0x39, 0xd8, 0xa0, 0xa0,
0x8a, 0x6b, 0xd8, 0x4d, 0x41, 0x7f, 0x97, 0x5c, 0x8e, 0x25, 0x7b, 0x24,
0x72, 0x1a, 0x46, 0xac, 0x8f, 0x8e, 0xd7, 0xe8, 0xa6, 0x31, 0x1e, 0x7c,
0xd0, 0xa9, 0x31, 0x84, 0xa6, 0x60, 0x73, 0xb3, 0xb9, 0x26, 0xa3, 0x4e,
0xd5, 0x03, 0x3f, 0xef, 0xaa, 0x5a, 0x41, 0x8d, 0x1f, 0x0b, 0xb6, 0x37,
0x63, 0x9b, 0xa1, 0xfe, 0x43, 0x5b, 0x73, 0xa2, 0x5b, 0xce, 0x53, 0x61,
0x05, 0x1f, 0x75, 0x35, 0xf1, 0x71, 0x5b, 0xf6, 0x60, 0x1e, 0xcc, 0x62,
0xae, 0xca, 0xe3, 0x4f, 0xc0, 0xc0, 0xfd, 0xe1, 0x42, 0xc3, 0xbc, 0x29,
0x84, 0x74, 0x30, 0x0a, 0x22, 0x69, 0x10, 0x3d, 0xb6, 0x7c, 0x54, 0xc7,
0x54, 0xe2, 0xaf, 0x3a, 0xee, 0xa3, 0x05, 0xd4, 0x89, 0xa2, 0xc3, 0xa1,
0x51, 0x45, 0x25, 0x8e, 0xc5, 0x5a, 0xc8, 0x75, 0x50, 0xd9, 0x98, 0x67,
0x3c, 0xd2, 0xfa, 0x96, 0x6a, 0xaa, 0x1b, 0x0a, 0x29, 0x15, 0xfe, 0xd0,
0xbb, 0x1a, 0xf5, 0xa4, 0xcd, 0xbe, 0xce, 0xa2, 0x3e, 0x0c, 0x03, 0x9c,
0xab, 0x3a, 0x34, 0xe2, 0x0e, 0x0e, 0xa0, 0xb3, 0x9a, 0x2a, 0x3f, 0xa2,
0x1e, 0xd3, 0x33, 0x38, 0x42, 0x6e, 0x65, 0xf8, 0xda, 0xfa, 0x90, 0x73,
0xa5, 0x66, 0x84, 0xe0, 0xfe, 0x99, 0xe9, 0xc1, 0x94, 0x24, 0x04, 0x7f,
0x05, 0xda, 0xc7, 0xcd, 0xce, 0x16, 0xfe, 0xfd, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x04,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
WOLFSSL_CTX *ctx_c = NULL;
WOLFSSL *ssl_c = NULL;
struct test_memio_ctx test_ctx;
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, NULL, &ssl_c, NULL,
wolfDTLSv1_2_client_method, NULL), 0);
/* start handshake, send first ClientHello */
ExpectIntEQ(wolfSSL_connect(ssl_c), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
ExpectIntEQ(test_memio_inject_message(&test_ctx, 1,
(const char*)certreq_before_cert_bin,
sizeof(certreq_before_cert_bin)), 0);
ExpectIntEQ(wolfSSL_connect(ssl_c), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), OUT_OF_ORDER_E);
wolfSSL_free(ssl_c);
wolfSSL_CTX_free(ctx_c);
#endif
return EXPECT_RESULT();
}
#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_DTLS)
struct {
struct test_memio_ctx* test_ctx;
WOLFSSL* ssl_s;
int fd;
SOCKADDR_S peer_addr;
} test_memio_wolfio_ctx;
static ssize_t test_memio_wolfio_recvfrom(int sockfd, void* buf,
size_t len, int flags, void* src_addr, void* addrlen)
{
int ret;
(void)flags;
if (sockfd != test_memio_wolfio_ctx.fd) {
errno = EINVAL;
return -1;
}
ret = test_memio_read_cb(test_memio_wolfio_ctx.ssl_s,
(char*)buf, (int)len, test_memio_wolfio_ctx.test_ctx);
if (ret <= 0) {
if (ret == WC_NO_ERR_TRACE(WOLFSSL_CBIO_ERR_WANT_READ))
errno = EAGAIN;
else
errno = EINVAL;
return -1;
}
XMEMCPY(src_addr, &test_memio_wolfio_ctx.peer_addr,
MIN(sizeof(test_memio_wolfio_ctx.peer_addr),
*(word32*)addrlen));
*(word32*)addrlen = sizeof(test_memio_wolfio_ctx.peer_addr);
return ret;
}
static ssize_t test_memio_wolfio_sendto(int sockfd, const void* buf,
size_t len, int flags, const void* dest_addr, word32 addrlen)
{
int ret;
(void) flags;
(void) dest_addr;
(void) addrlen;
if (sockfd != test_memio_wolfio_ctx.fd) {
errno = EINVAL;
return -1;
}
if (dest_addr != NULL && addrlen != 0 &&
(sizeof(test_memio_wolfio_ctx.peer_addr) != addrlen ||
XMEMCMP(dest_addr, &test_memio_wolfio_ctx.peer_addr,
addrlen) != 0)) {
errno = EINVAL;
return -1;
}
ret = test_memio_write_cb(test_memio_wolfio_ctx.ssl_s, (char*)buf,
(int)len, test_memio_wolfio_ctx.test_ctx);
if (ret <= 0) {
if (ret == WC_NO_ERR_TRACE(WOLFSSL_CBIO_ERR_WANT_WRITE))
errno = EAGAIN;
else
errno = EINVAL;
return -1;
}
return ret;
}
#endif
/* Test stateless API with wolfio */
int test_dtls_memio_wolfio(void)
{
EXPECT_DECLS;
#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_DTLS)
size_t i;
struct {
method_provider client_meth;
method_provider server_meth;
} params[] = {
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_DTLS13)
{ wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method },
#endif
#if !defined(WOLFSSL_NO_TLS12) && defined(WOLFSSL_DTLS)
{ wolfDTLSv1_2_client_method, wolfDTLSv1_2_server_method },
#endif
#if !defined(NO_OLD_TLS) && defined(WOLFSSL_DTLS)
{ wolfDTLSv1_client_method, wolfDTLSv1_server_method },
#endif
};
XMEMSET(&test_memio_wolfio_ctx, 0, sizeof(test_memio_wolfio_ctx));
for (i = 0; i < XELEM_CNT(params) && !EXPECT_FAIL(); i++) {
WOLFSSL_CTX *ctx_c = NULL, *ctx_s = NULL;
WOLFSSL *ssl_c = NULL, *ssl_s = NULL;
struct test_memio_ctx test_ctx;
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
params[i].client_meth, params[i].server_meth), 0);
test_memio_wolfio_ctx.test_ctx = &test_ctx;
test_memio_wolfio_ctx.ssl_s = ssl_s;
/* Large number to error out if any syscalls are called with it */
test_memio_wolfio_ctx.fd = 6000;
XMEMSET(&test_memio_wolfio_ctx.peer_addr, 0,
sizeof(test_memio_wolfio_ctx.peer_addr));
test_memio_wolfio_ctx.peer_addr.ss_family = AF_INET;
wolfSSL_dtls_set_using_nonblock(ssl_s, 1);
wolfSSL_SetRecvFrom(ssl_s, test_memio_wolfio_recvfrom);
wolfSSL_SetSendTo(ssl_s, test_memio_wolfio_sendto);
/* Restore default functions */
wolfSSL_SSLSetIORecv(ssl_s, EmbedReceiveFrom);
wolfSSL_SSLSetIOSend(ssl_s, EmbedSendTo);
ExpectIntEQ(wolfSSL_set_fd(ssl_s, test_memio_wolfio_ctx.fd),
WOLFSSL_SUCCESS);
ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0);
wolfSSL_free(ssl_s);
wolfSSL_free(ssl_c);
wolfSSL_CTX_free(ctx_s);
wolfSSL_CTX_free(ctx_c);
}
#endif
return EXPECT_RESULT();
}
/* DTLS using stateless API handling new addresses with wolfio */
int test_dtls_memio_wolfio_stateless(void)
{
EXPECT_DECLS;
#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_DTLS)
size_t i, j;
struct {
method_provider client_meth;
method_provider server_meth;
} params[] = {
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_DTLS13)
{ wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method },
#endif
#if !defined(WOLFSSL_NO_TLS12) && defined(WOLFSSL_DTLS)
{ wolfDTLSv1_2_client_method, wolfDTLSv1_2_server_method },
#endif
#if !defined(NO_OLD_TLS) && defined(WOLFSSL_DTLS)
{ wolfDTLSv1_client_method, wolfDTLSv1_server_method },
#endif
};
XMEMSET(&test_memio_wolfio_ctx, 0, sizeof(test_memio_wolfio_ctx));
for (i = 0; i < XELEM_CNT(params) && !EXPECT_FAIL(); i++) {
WOLFSSL_CTX *ctx_c = NULL, *ctx_s = NULL;
WOLFSSL *ssl_c = NULL, *ssl_s = NULL;
struct test_memio_ctx test_ctx;
char chBuf[1000];
int chSz = sizeof(chBuf);
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
params[i].client_meth, params[i].server_meth), 0);
test_memio_wolfio_ctx.test_ctx = &test_ctx;
test_memio_wolfio_ctx.ssl_s = ssl_s;
/* Large number to error out if any syscalls are called with it */
test_memio_wolfio_ctx.fd = 6000;
XMEMSET(&test_memio_wolfio_ctx.peer_addr, 0,
sizeof(test_memio_wolfio_ctx.peer_addr));
test_memio_wolfio_ctx.peer_addr.ss_family = AF_INET;
wolfSSL_dtls_set_using_nonblock(ssl_s, 1);
wolfSSL_SetRecvFrom(ssl_s, test_memio_wolfio_recvfrom);
/* Restore default functions */
wolfSSL_SSLSetIORecv(ssl_s, EmbedReceiveFrom);
ExpectIntEQ(wolfSSL_set_read_fd(ssl_s, test_memio_wolfio_ctx.fd),
WOLFSSL_SUCCESS);
/* start handshake, send first ClientHello */
ExpectIntEQ(wolfSSL_connect(ssl_c), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
ExpectIntEQ(test_memio_copy_message(&test_ctx, 0, chBuf, &chSz, 0), 0);
ExpectIntGT(chSz, 0);
test_memio_clear_buffer(&test_ctx, 0);
/* Send CH from different addresses */
for (j = 0; j < 10 && !EXPECT_FAIL(); j++,
(((SOCKADDR_IN*)&test_memio_wolfio_ctx.peer_addr))->sin_port++) {
const char* hrrBuf = NULL;
int hrrSz = 0;
ExpectIntEQ(test_memio_inject_message(&test_ctx, 0, chBuf, chSz), 0);
ExpectIntEQ(wolfDTLS_accept_stateless(ssl_s), 0);
ExpectIntEQ(test_memio_get_message(&test_ctx, 1, &hrrBuf, &hrrSz, 0), 0);
ExpectNotNull(hrrBuf);
ExpectIntGT(hrrSz, 0);
test_memio_clear_buffer(&test_ctx, 0);
}
test_memio_clear_buffer(&test_ctx, 1);
ExpectIntEQ(wolfSSL_dtls_got_timeout(ssl_c), 1);
ExpectIntEQ(wolfDTLS_accept_stateless(ssl_s), 0);
ExpectIntEQ(wolfSSL_connect(ssl_c), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
ExpectIntEQ(wolfDTLS_accept_stateless(ssl_s), 1);
ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0);
wolfSSL_free(ssl_s);
wolfSSL_free(ssl_c);
wolfSSL_CTX_free(ctx_s);
wolfSSL_CTX_free(ctx_c);
}
#endif
return EXPECT_RESULT();
}
int test_dtls_mtu_split_messages(void)
{
#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \
defined(WOLFSSL_DTLS_MTU) && defined(WOLFSSL_NO_DTLS_SIZE_CHECK) && \
defined(HAVE_AESGCM) && defined(HAVE_ECC)
EXPECT_DECLS;
struct {
method_provider client_meth;
method_provider server_meth;
const char* cipher;
} params[] = {
#if defined(WOLFSSL_DTLS13) && defined(WOLFSSL_TLS13)
{ wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method,
"TLS13-AES128-GCM-SHA256" },
#endif
#if defined(WOLFSSL_DTLS) && !defined(WOLFSSL_NO_TLS12)
{ wolfDTLSv1_2_client_method, wolfDTLSv1_2_server_method,
"ECDHE-RSA-AES128-GCM-SHA256" },
#if !defined(WOLFSSL_AEAD_ONLY) && !defined(NO_AES) && !defined(NO_SHA)
/* Block cipher test */
{ wolfDTLSv1_2_client_method, wolfDTLSv1_2_server_method,
"ECDHE-RSA-AES128-SHA" },
#endif
#endif
};
size_t i;
for (i = 0; i < XELEM_CNT(params) && EXPECT_SUCCESS(); i++) {
WOLFSSL_CTX *ctx_c = NULL, *ctx_s = NULL;
WOLFSSL *ssl_c = NULL, *ssl_s = NULL;
struct test_memio_ctx test_ctx;
/* Payload larger than typical MTU to force splitting */
unsigned char payload[200];
unsigned char readBuf[200];
word16 mtu;
int recordLen;
int overhead;
int totalRead;
int ret;
int j;
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
XMEMSET(payload, 'A', sizeof(payload));
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
params[i].client_meth, params[i].server_meth),
0);
ExpectIntEQ(wolfSSL_set_cipher_list(ssl_c, params[i].cipher), 1);
ExpectIntEQ(wolfSSL_set_cipher_list(ssl_s, params[i].cipher), 1);
/* Complete handshake and clear any leftover records. */
ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0);
test_memio_clear_buffer(&test_ctx, 1);
test_memio_clear_buffer(&test_ctx, 0);
/* Measure application-data record overhead with small payload. */
ExpectIntEQ(wolfSSL_write(ssl_c, payload, 32), 32);
ExpectIntEQ(test_ctx.s_msg_count, 1);
recordLen = test_ctx.s_len;
ExpectIntGT(recordLen, 32);
overhead = recordLen - 32;
/* Reset buffers before MTU-limited send. */
test_memio_clear_buffer(&test_ctx, 0);
test_memio_clear_buffer(&test_ctx, 1);
/* Set MTU to allow only ~50 bytes of payload per record.
* This ensures a 200-byte payload must be split into multiple msgs. */
mtu = (word16)(overhead + 50);
ExpectIntEQ(wolfSSL_dtls_set_mtu(ssl_c, mtu), WOLFSSL_SUCCESS);
ExpectIntEQ(wolfSSL_dtls_set_mtu(ssl_s, mtu), WOLFSSL_SUCCESS);
/* Write payload larger than MTU allows in single record.
* With WOLFSSL_NO_DTLS_SIZE_CHECK, this should split into multiple
* messages instead of returning DTLS_SIZE_ERROR. */
ExpectIntEQ(wolfSSL_write(ssl_c, payload, (int)sizeof(payload)),
(int)sizeof(payload));
/* Verify multiple messages were sent */
ExpectIntGT(test_ctx.s_msg_count, 1);
/* Each record should fit within MTU */
for (j = 0; j < test_ctx.s_msg_count && EXPECT_SUCCESS(); j++) {
ExpectIntLE(test_ctx.s_msg_sizes[j], mtu);
}
/* Read all data on server side and verify it matches */
totalRead = 0;
while (totalRead < (int)sizeof(payload) && EXPECT_SUCCESS()) {
ret = wolfSSL_read(ssl_s, readBuf + totalRead,
(int)sizeof(readBuf) - totalRead);
if (ret > 0) {
totalRead += ret;
}
else {
break;
}
}
ExpectIntEQ(totalRead, (int)sizeof(payload));
ExpectIntEQ(XMEMCMP(payload, readBuf, sizeof(payload)), 0);
wolfSSL_free(ssl_c);
wolfSSL_CTX_free(ctx_c);
wolfSSL_free(ssl_s);
wolfSSL_CTX_free(ctx_s);
}
return EXPECT_RESULT();
#else
return TEST_SKIPPED;
#endif
}
/* Test DTLS 1.3 minimum retransmission interval. This test calls
* wolfSSL_dtls_got_timeout() to simulate timeouts and verify that
* retransmissions are spaced at least DTLS13_MIN_RTX_INTERVAL apart.
* This tests relies on timing of the retransmission logic so it may be
* flaky on very slow systems.
*/
int test_dtls13_min_rtx_interval(void)
{
EXPECT_DECLS;
#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \
defined(WOLFSSL_DTLS13) && !defined(DTLS13_MIN_RTX_INTERVAL) && \
!defined(NO_ASN_TIME)
/* We don't want to test when DTLS13_MIN_RTX_INTERVAL is defined because
* it may be too low to trigger reliably in a test. The default value is
* 1 second which is sufficient for testing here. */
WOLFSSL_CTX *ctx_c = NULL, *ctx_s = NULL;
WOLFSSL *ssl_c = NULL, *ssl_s = NULL;
struct test_memio_ctx test_ctx;
int c_msg_count = 0;
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
/* Setup DTLS 1.3 contexts */
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method), 0);
/* CH0 */
ExpectIntEQ(wolfSSL_connect(ssl_c), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), SSL_ERROR_WANT_READ);
/* HRR */
ExpectIntEQ(wolfSSL_accept(ssl_s), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), SSL_ERROR_WANT_READ);
/* CH1 */
ExpectIntEQ(wolfSSL_connect(ssl_c), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), SSL_ERROR_WANT_READ);
/* SH ... FINISHED */
ExpectIntEQ(wolfSSL_accept(ssl_s), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), SSL_ERROR_WANT_READ);
/* We should have SH ... FINISHED messages in the buffer */
ExpectIntGE(test_ctx.c_msg_count, 2);
/* Drop everything */
test_memio_clear_buffer(&test_ctx, 1);
/* First timeout. This one should trigger a retransmission */
if (wolfSSL_dtls13_use_quick_timeout(ssl_s))
ExpectIntEQ(wolfSSL_dtls_got_timeout(ssl_s), WOLFSSL_SUCCESS);
ExpectIntEQ(wolfSSL_dtls_got_timeout(ssl_s), WOLFSSL_SUCCESS);
/* Save the message count to make sure no new messages are sent */
ExpectIntGE(test_ctx.c_msg_count, 2);
c_msg_count = test_ctx.c_msg_count;
/* Second timeout. This one should not trigger a retransmission */
if (wolfSSL_dtls13_use_quick_timeout(ssl_s))
ExpectIntEQ(wolfSSL_dtls_got_timeout(ssl_s), WOLFSSL_SUCCESS);
ExpectIntEQ(wolfSSL_dtls_got_timeout(ssl_s), WOLFSSL_SUCCESS);
/* This is the critical check. The message count should not increase
* after the second timeout. DTLS13_MIN_RTX_INTERVAL should have blocked
* retransmission here. */
ExpectIntEQ(c_msg_count, test_ctx.c_msg_count);
/* Now complete the handshake. We didn't clear the first retransmission
* so the handshake should proceed without issues. */
ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0);
/* Cleanup */
wolfSSL_free(ssl_c);
wolfSSL_CTX_free(ctx_c);
wolfSSL_free(ssl_s);
wolfSSL_CTX_free(ctx_s);
#endif
return EXPECT_RESULT();
}