Files
wolfssl/tests/utils.h
T
Tobias Frauenschläger 9b4f00df6b Cover the DTLS 1.3 scheduled work API in the tests
Several DTLS tests drive a connection with reads alone and then assert that
something was sent, an ACK in most cases. With WOLFSSL_RW_THREADED that only
happens once the application asks for it, so stand in for such an application
and pump where the send is expected. The helper is a no-op elsewhere, so
builds whose read path sends for itself are unchanged.

test_dtls13_ack_overflow needs the same treatment in its setup, where the ACK
the first reads scheduled would otherwise be left in the seen-record list and
counted by the assertions that follow. It sits in the dtls13 group rather than
dtls, so a run of the dtls group alone does not cover it.

Add a test for the new API that runs in every build rather than only the
threaded one. It schedules a key update the way the AEAD failure limit does
and requires the predicate to report it, the pump to perform it and put a
record on the wire, and the wait for the peer's acknowledgement not to be
reported as work. It then drives the state that would wedge a drain loop, a
peer requesting a KeyUpdate while ours is unacknowledged, and requires pump
and predicate to agree that nothing can be sent and the request to be kept
until it can. It also covers the bad argument cases, a DTLS 1.2 object being
refused rather than quietly succeeding, and that refusing an object records no
error against the connection and leaves it usable.

The AEAD limit test excludes its second key update and its hard limit check
from threaded builds. Both need the acknowledgement processing that stays off
the write path: without it the decrypting epoch stops matching the one the
drop counter is placed on, so the read never reaches the limit and the test
hangs rather than failing.
2026-08-01 12:04:57 +02:00

143 lines
6.1 KiB
C

/* utils.h
*
* Copyright (C) 2006-2026 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 <wolfssl/wolfcrypt/settings.h>
#include <wolfssl/wolfcrypt/types.h>
#include <wolfssl/ssl.h>
#include <wolfssl/test.h>
#ifndef TESTS_UTILS_H
#define TESTS_UTILS_H
#ifdef WOLFSSL_DUMP_MEMIO_STREAM
extern char tmpDirName[16];
extern const char* currentTestName;
#endif
/* Base dependencies for the manual memio test harness. The harness itself does
* not require certificate support, so cert-less tests (e.g. PSK-only) can use
* it through this narrower macro. */
#if !defined(NO_WOLFSSL_SERVER) && !defined(NO_WOLFSSL_CLIENT) && \
(!defined(WOLFSSL_NO_TLS12) || defined(WOLFSSL_TLS13)) && defined(NO_CERTS)
#define HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES_NO_CERTS
#define HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES_BUILD
#endif
/* Full dependencies: the base harness plus certificate support. Most memio
* tests set up a certificate-based handshake and must use this macro. */
#if !defined(NO_WOLFSSL_SERVER) && !defined(NO_WOLFSSL_CLIENT) && \
(!defined(WOLFSSL_NO_TLS12) || defined(WOLFSSL_TLS13)) && \
!defined(NO_FILESYSTEM) && !defined(NO_CERTS) && \
(!defined(NO_RSA) || defined(HAVE_RPK))
#define HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES
#define HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES_BUILD
#endif
/* With WOLFSSL_RW_THREADED the read path never transmits, so anything a read
* schedules to be sent, an ACK in particular, is only sent from the write
* side. Stand in for the application, which is required to pump that work
* from its write thread. A no-op in builds where reads send for themselves. */
#if defined(WOLFSSL_DTLS13) && defined(WOLFSSL_RW_THREADED) && \
!defined(WOLFSSL_LEANPSK)
#define TEST_DTLS13_PUMP(ssl) \
do { \
ExpectIntEQ(wolfSSL_dtls13_do_scheduled_work(ssl), \
WOLFSSL_SUCCESS); \
} while (0)
#else
#define TEST_DTLS13_PUMP(ssl) \
do { \
(void)(ssl); \
} while (0)
#endif
#ifdef HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES_BUILD
#define TEST_MEMIO_BUF_SZ (64 * 1024)
#define TEST_MEMIO_MAX_MSGS 32
struct test_memio_ctx
{
byte c_buff[TEST_MEMIO_BUF_SZ];
int c_len;
const char* c_ciphers;
byte s_buff[TEST_MEMIO_BUF_SZ];
int s_len;
const char* s_ciphers;
int c_force_want_write;
int s_force_want_write;
int c_msg_sizes[TEST_MEMIO_MAX_MSGS];
int c_msg_count;
int c_msg_pos;
int s_msg_sizes[TEST_MEMIO_MAX_MSGS];
int s_msg_count;
int s_msg_pos;
};
int test_memio_write_cb(WOLFSSL *ssl, char *data, int sz, void *ctx);
int test_memio_read_cb(WOLFSSL *ssl, char *data, int sz, void *ctx);
int test_memio_do_handshake(WOLFSSL *ssl_c, WOLFSSL *ssl_s,
int max_rounds, int *rounds);
int test_memio_setup(struct test_memio_ctx *ctx,
WOLFSSL_CTX **ctx_c, WOLFSSL_CTX **ctx_s, WOLFSSL **ssl_c, WOLFSSL **ssl_s,
method_provider method_c, method_provider method_s);
int test_memio_setup_ex(struct test_memio_ctx *ctx,
WOLFSSL_CTX **ctx_c, WOLFSSL_CTX **ctx_s, WOLFSSL **ssl_c, WOLFSSL **ssl_s,
method_provider method_c, method_provider method_s,
byte *caCert, int caCertSz, byte *serverCert, int serverCertSz,
byte *serverKey, int serverKeySz);
void test_memio_simulate_want_write(struct test_memio_ctx *ctx, int is_client,
int enable);
void test_memio_clear_buffer(struct test_memio_ctx *ctx, int is_client);
int test_memio_inject_message(struct test_memio_ctx *ctx, int client, const char *data, int sz);
int test_memio_copy_message(const struct test_memio_ctx *ctx, int client,
char *out, int *out_sz, int msg_pos);
int test_memio_get_message(const struct test_memio_ctx *ctx, int client,
const char **out, int *out_sz, int msg_pos);
int test_memio_msg_is_hello_retry_request(const struct test_memio_ctx *ctx);
int test_memio_move_message(struct test_memio_ctx *ctx, int client,
int msg_pos_in, int msg_pos_out);
int test_memio_drop_message(struct test_memio_ctx *ctx, int client, int msg_pos);
int test_memio_modify_message_len(struct test_memio_ctx *ctx, int client, int msg_pos, int new_len);
int test_memio_remove_from_buffer(struct test_memio_ctx *ctx, int client, int off, int sz);
#endif /* HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES_BUILD */
/* Shared TLS server/client thread bodies, defined in tests/api.c. The
* definitions are gated on ENABLE_TLS_CALLBACK_TEST (a composite condition
* locally #defined inside api.c) or (WOLFSSL_DTLS && WOLFSSL_SESSION_EXPORT).
* Declared unconditionally here so api.c itself sees the prototype regardless
* of which side of the local #define triggers; absent the definition the
* prototypes are harmless and any caller would get a link error. */
THREAD_RETURN WOLFSSL_THREAD run_wolfssl_server(void* args);
void run_wolfssl_client(void* args);
#if !defined(NO_FILESYSTEM) && defined(OPENSSL_EXTRA) && \
defined(DEBUG_UNIT_TEST_CERTS)
void DEBUG_WRITE_CERT_X509(WOLFSSL_X509* x509, const char* fileName);
void DEBUG_WRITE_DER(const byte* der, int derSz, const char* fileName);
#else
#define DEBUG_WRITE_CERT_X509(x509, fileName) WC_DO_NOTHING
#define DEBUG_WRITE_DER(der, derSz, fileName) WC_DO_NOTHING
#endif
#endif /* TESTS_UTILS_H */