From b4ec5423044982c2b2b2b182abe4cb2b99808e57 Mon Sep 17 00:00:00 2001 From: jsing <> Date: Sat, 25 Apr 2026 14:36:12 +0000 Subject: Add DTLS wire tests. Add tests that ensure the wire bytes for DTLS are what we expect for both CCS and fragmented handshake messages. --- src/regress/lib/libssl/dtls/Makefile | 14 +- src/regress/lib/libssl/dtls/dtls_wire_test.c | 376 +++++++++++++++++++++++++++ 2 files changed, 386 insertions(+), 4 deletions(-) create mode 100644 src/regress/lib/libssl/dtls/dtls_wire_test.c (limited to 'src') diff --git a/src/regress/lib/libssl/dtls/Makefile b/src/regress/lib/libssl/dtls/Makefile index b58dae61b6..a8d888c882 100644 --- a/src/regress/lib/libssl/dtls/Makefile +++ b/src/regress/lib/libssl/dtls/Makefile @@ -1,6 +1,8 @@ -# $OpenBSD: Makefile,v 1.4 2024/03/20 10:38:05 jsing Exp $ +# $OpenBSD: Makefile,v 1.5 2026/04/25 14:36:12 jsing Exp $ + +PROGS += dtlstest +PROGS += dtls_wire_test -PROG= dtlstest LDADD= ${SSL_INT} -lcrypto DPADD= ${LIBSSL} ${LIBCRYPTO} WARNINGS= Yes @@ -9,13 +11,17 @@ CFLAGS+= -I${.CURDIR}/../../../../lib/libcrypto/bio CFLAGS+= -I${.CURDIR}/../../../../lib/libssl REGRESS_TARGETS= \ - regress-dtlstest + regress-dtlstest \ + regress-dtls_wire_test # XXX(jsing): use CA root and chain -regress-dtlstest: ${PROG} +regress-dtlstest: dtlstest ./dtlstest \ ${.CURDIR}/../../libssl/certs/server1-rsa.pem \ ${.CURDIR}/../../libssl/certs/server1-rsa.pem \ ${.CURDIR}/../../libssl/certs/ca-int-rsa.pem +regress-dtls_wire_test: dtls_wire_test + ./dtls_wire_test + .include diff --git a/src/regress/lib/libssl/dtls/dtls_wire_test.c b/src/regress/lib/libssl/dtls/dtls_wire_test.c new file mode 100644 index 0000000000..fa9717a3e1 --- /dev/null +++ b/src/regress/lib/libssl/dtls/dtls_wire_test.c @@ -0,0 +1,376 @@ +/* $OpenBSD: dtls_wire_test.c,v 1.1 2026/04/25 14:36:12 jsing Exp $ */ +/* + * Copyright (c) 2026 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include +#include + +#include "dtls_local.h" +#include "ssl_local.h" + +static void +hexdump(const unsigned char *buf, size_t len) +{ + size_t i; + + for (i = 1; i <= len; i++) + fprintf(stderr, " 0x%02hhx,%s", buf[i - 1], i % 8 ? "" : "\n"); + + fprintf(stderr, "\n"); +} + +static const uint8_t dtls12_hm_wire_bytes[] = { + 0x16, 0xfe, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0xf3, 0x16, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0xe7, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x16, 0xfe, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x01, 0xf3, 0x16, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x01, 0xe7, 0x00, 0x01, + 0xe7, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x16, 0xfe, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x3e, 0x16, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x03, 0xce, 0x00, 0x00, + 0x32, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x41, 0x41, 0x41, +}; + +static int +dtls_send_handshake_message_test(void) +{ + BIO *rbio = NULL, *wbio = NULL; + char *wbuf, rbuf[1]; + CBB handshake, body; + uint8_t *p; + SSL_CTX *ssl_ctx = NULL; + SSL *ssl = NULL; + long len; + int failed = 1; + + if ((ssl_ctx = SSL_CTX_new(DTLS_client_method())) == NULL) { + fprintf(stderr, "FAIL: failed to create SSL_CTX\n"); + goto failure; + } + if ((ssl = SSL_new(ssl_ctx)) == NULL) { + fprintf(stderr, "FAIL: failed to create SSL\n"); + goto failure; + } + + if ((rbio = BIO_new_mem_buf(rbuf, sizeof(rbuf))) == NULL) { + fprintf(stderr, "FAIL: failed to create rbio\n"); + goto failure; + } + if ((wbio = BIO_new(BIO_s_mem())) == NULL) { + fprintf(stderr, "FAIL: failed to create wbio\n"); + goto failure; + } + + BIO_up_ref(rbio); + BIO_up_ref(wbio); + SSL_set_bio(ssl, rbio, wbio); + + if (!ssl3_setup_init_buffer(ssl)) { + fprintf(stderr, "FAIL: failed to setup init buffer\n"); + goto failure; + } + if (!ssl3_setup_write_buffer(ssl)) { + fprintf(stderr, "FAIL: failed to setup write buffer\n"); + goto failure; + } + if (!ssl_get_new_session(ssl, 0)) { + fprintf(stderr, "FAIL: failed to create session\n"); + goto failure; + } + if (!tls1_transcript_init(ssl)) { + fprintf(stderr, "FAIL: failed to init transcript\n"); + goto failure; + } + + ssl->s3->hs.cipher = ssl3_get_cipher_by_value( + TLS1_CK_ECDHE_RSA_WITH_AES_128_SHA256 & 0xffff); + + ssl->s3->hs.state = SSL3_ST_CW_CLNT_HELLO_B; + ssl->d1->mtu = 512; + + if (!ssl3_handshake_msg_start(ssl, &handshake, &body, SSL3_RT_HANDSHAKE)) { + fprintf(stderr, "FAIL: failed to start handshake message\n"); + goto failure; + } + if (!CBB_add_space(&body, &p, 1024)) + goto failure; + memset(p, 'A', 1024); + if (!ssl3_handshake_msg_finish(ssl, &handshake)) { + fprintf(stderr, "FAIL: failed to finish handshake message\n"); + goto failure; + } + + ssl3_connect(ssl); + + if (ssl->s3->hs.state != SSL3_ST_CR_SRVR_HELLO_A) { + fprintf(stderr, "FAIL: got state 0x%x, want 0x%x\n", + ssl->s3->hs.state, SSL3_ST_CR_SRVR_HELLO_A); + goto failure; + } + + if ((len = BIO_get_mem_data(wbio, &wbuf)) != sizeof(dtls12_hm_wire_bytes)) { + fprintf(stderr, "FAIL: got handshake message length = %ld, want %zu\n", + len, sizeof(dtls12_hm_wire_bytes)); + goto failure; + } + if (memcmp(wbuf, dtls12_hm_wire_bytes, len) != 0) { + fprintf(stderr, "FAIL: got handshake message wire bytes:\n"); + hexdump(wbuf, len); + fprintf(stderr, "want handshake message wire bytes:\n"); + hexdump(dtls12_hm_wire_bytes, len); + } + + failed = 0; + + failure: + SSL_CTX_free(ssl_ctx); + SSL_free(ssl); + + BIO_free(rbio); + BIO_free(wbio); + + return failed; +} + +static const uint8_t dtls12_ccs_wire_bytes[] = { + 0x14, 0xfe, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, +}; + +static int +dtls_send_ccs_test(void) +{ + BIO *rbio = NULL, *wbio = NULL; + char *wbuf, rbuf[1]; + SSL_CTX *ssl_ctx = NULL; + SSL *ssl = NULL; + long len; + int failed = 1; + + if ((ssl_ctx = SSL_CTX_new(DTLS_client_method())) == NULL) { + fprintf(stderr, "FAIL: failed to create SSL_CTX\n"); + goto failure; + } + if ((ssl = SSL_new(ssl_ctx)) == NULL) { + fprintf(stderr, "FAIL: failed to create SSL\n"); + goto failure; + } + + if ((rbio = BIO_new_mem_buf(rbuf, sizeof(rbuf))) == NULL) { + fprintf(stderr, "FAIL: failed to create rbio\n"); + goto failure; + } + if ((wbio = BIO_new(BIO_s_mem())) == NULL) { + fprintf(stderr, "FAIL: failed to create wbio\n"); + goto failure; + } + + BIO_up_ref(rbio); + BIO_up_ref(wbio); + SSL_set_bio(ssl, rbio, wbio); + + if (!ssl3_setup_init_buffer(ssl)) { + fprintf(stderr, "FAIL: failed to setup init buffer\n"); + goto failure; + } + if (!ssl3_setup_write_buffer(ssl)) { + fprintf(stderr, "FAIL: failed to setup write buffer\n"); + goto failure; + } + if (!ssl_get_new_session(ssl, 0)) { + fprintf(stderr, "FAIL: failed to create session\n"); + goto failure; + } + + ssl->s3->hs.cipher = ssl3_get_cipher_by_value( + TLS1_CK_ECDHE_RSA_WITH_AES_128_SHA256 & 0xffff); + + ssl->s3->hs.state = SSL3_ST_CW_CHANGE_A; + ssl->d1->mtu = 512; + + ssl3_connect(ssl); + + if (ssl->s3->hs.state != SSL3_ST_CW_FINISHED_A) { + fprintf(stderr, "FAIL: got state 0x%x, want 0x%x\n", + ssl->s3->hs.state, SSL3_ST_CW_FINISHED_A); + goto failure; + } + + if ((len = BIO_get_mem_data(wbio, &wbuf)) != sizeof(dtls12_ccs_wire_bytes)) { + fprintf(stderr, "FAIL: got CCS length = %ld, want %zu\n", len, + sizeof(dtls12_ccs_wire_bytes)); + goto failure; + } + if (memcmp(wbuf, dtls12_ccs_wire_bytes, len) != 0) { + fprintf(stderr, "FAIL: got CCS wire bytes:\n"); + hexdump(wbuf, len); + fprintf(stderr, "want CCS wire bytes:\n"); + hexdump(dtls12_ccs_wire_bytes, len); + } + + failed = 0; + + failure: + SSL_CTX_free(ssl_ctx); + SSL_free(ssl); + + BIO_free(rbio); + BIO_free(wbio); + + return failed; +} + +int +main(int argc, char **argv) +{ + int failed = 0; + + failed |= dtls_send_handshake_message_test(); + failed |= dtls_send_ccs_test(); + + return failed; +} -- cgit v1.2.3-55-g6feb