summaryrefslogtreecommitdiff
path: root/test/helpers
diff options
context:
space:
mode:
authorMatt Caswell <matt@openssl.org>2022-12-12 16:52:50 +0000
committerHugo Landau <hlandau@openssl.org>2023-02-22 05:34:04 +0000
commitde60deb258c4b52502da372a61344b83428fc970 (patch)
tree8d2a1b10f4b949dcbb8a7eb9cf64f6c32636bf72 /test/helpers
parentda81f1e563c80a1d4ab82e545f3f5ba6e715267e (diff)
downloadopenssl-new-de60deb258c4b52502da372a61344b83428fc970.tar.gz
Enable the fault injector to add faults to post-encryption packets
Reviewed-by: Hugo Landau <hlandau@openssl.org> Reviewed-by: Tomas Mraz <tomas@openssl.org> (Merged from https://github.com/openssl/openssl/pull/20030)
Diffstat (limited to 'test/helpers')
-rw-r--r--test/helpers/quictestlib.c176
-rw-r--r--test/helpers/quictestlib.h18
2 files changed, 170 insertions, 24 deletions
diff --git a/test/helpers/quictestlib.c b/test/helpers/quictestlib.c
index b9c437ba57..26d52600b2 100644
--- a/test/helpers/quictestlib.c
+++ b/test/helpers/quictestlib.c
@@ -8,6 +8,7 @@
*/
#include <assert.h>
+#include <openssl/bio.h>
#include "quictestlib.h"
#include "../testutil.h"
#include "internal/quic_wire_pkt.h"
@@ -41,11 +42,17 @@ struct ossl_quic_fault {
void *handshakecbarg;
ossl_quic_fault_on_enc_ext_cb encextcb;
void *encextcbarg;
+
+ /* Cipher packet mutations */
+ ossl_quic_fault_on_packet_cipher_cb pciphercb;
+ void *pciphercbarg;
};
static void packet_plain_finish(void *arg);
static void handshake_finish(void *arg);
+static BIO_METHOD *get_bio_method(void);
+
int qtest_create_quic_objects(SSL_CTX *clientctx, char *certfile, char *keyfile,
QUIC_TSERVER **qtserv, SSL **cssl,
OSSL_QUIC_FAULT **fault)
@@ -53,7 +60,7 @@ int qtest_create_quic_objects(SSL_CTX *clientctx, char *certfile, char *keyfile,
/* ALPN value as recognised by QUIC_TSERVER */
unsigned char alpn[] = { 8, 'o', 's', 's', 'l', 't', 'e', 's', 't' };
QUIC_TSERVER_ARGS tserver_args = {0};
- BIO *bio1 = NULL, *bio2 = NULL;
+ BIO *cbio = NULL, *sbio = NULL, *fisbio = NULL;
BIO_ADDR *peeraddr = NULL;
struct in_addr ina = {0};
@@ -71,14 +78,14 @@ int qtest_create_quic_objects(SSL_CTX *clientctx, char *certfile, char *keyfile,
if (!TEST_false(SSL_set_alpn_protos(*cssl, alpn, sizeof(alpn))))
goto err;
- if (!TEST_true(BIO_new_bio_dgram_pair(&bio1, 0, &bio2, 0)))
+ if (!TEST_true(BIO_new_bio_dgram_pair(&cbio, 0, &sbio, 0)))
goto err;
- if (!TEST_true(BIO_dgram_set_caps(bio1, BIO_DGRAM_CAP_HANDLES_DST_ADDR))
- || !TEST_true(BIO_dgram_set_caps(bio2, BIO_DGRAM_CAP_HANDLES_DST_ADDR)))
+ if (!TEST_true(BIO_dgram_set_caps(cbio, BIO_DGRAM_CAP_HANDLES_DST_ADDR))
+ || !TEST_true(BIO_dgram_set_caps(sbio, BIO_DGRAM_CAP_HANDLES_DST_ADDR)))
goto err;
- SSL_set_bio(*cssl, bio1, bio1);
+ SSL_set_bio(*cssl, cbio, cbio);
if (!TEST_ptr(peeraddr = BIO_ADDR_new()))
goto err;
@@ -91,36 +98,43 @@ int qtest_create_quic_objects(SSL_CTX *clientctx, char *certfile, char *keyfile,
if (!TEST_true(SSL_set_initial_peer_addr(*cssl, peeraddr)))
goto err;
- /* 2 refs are passed for bio2 */
- if (!BIO_up_ref(bio2))
+ if (fault != NULL) {
+ *fault = OPENSSL_zalloc(sizeof(**fault));
+ if (*fault == NULL)
+ goto err;
+ }
+
+ fisbio = BIO_new(get_bio_method());
+ if (!TEST_ptr(fisbio))
+ goto err;
+
+ BIO_set_data(fisbio, fault == NULL ? NULL : *fault);
+
+ if (!TEST_ptr(BIO_push(fisbio, sbio)))
goto err;
- tserver_args.net_rbio = bio2;
- tserver_args.net_wbio = bio2;
+
+ tserver_args.net_rbio = sbio;
+ tserver_args.net_wbio = fisbio;
if (!TEST_ptr(*qtserv = ossl_quic_tserver_new(&tserver_args, certfile,
- keyfile))) {
- /* We hold 2 refs to bio2 at the moment */
- BIO_free(bio2);
+ keyfile)))
goto err;
- }
- /* Ownership of bio2 is now held by *qtserv */
- bio2 = NULL;
- if (fault != NULL) {
- *fault = OPENSSL_zalloc(sizeof(**fault));
- if (*fault == NULL)
- goto err;
+ /* Ownership of fisbio and sbio is now held by *qtserv */
+ sbio = NULL;
+ fisbio = NULL;
+ if (fault != NULL)
(*fault)->qtserv = *qtserv;
- }
BIO_ADDR_free(peeraddr);
return 1;
err:
BIO_ADDR_free(peeraddr);
- BIO_free(bio1);
- BIO_free(bio2);
+ BIO_free(cbio);
+ BIO_free(fisbio);
+ BIO_free(sbio);
SSL_free(*cssl);
ossl_quic_tserver_free(*qtserv);
if (fault != NULL)
@@ -518,3 +532,121 @@ int ossl_quic_fault_delete_extension(OSSL_QUIC_FAULT *fault,
return 1;
}
+
+#define BIO_TYPE_CIPHER_PACKET_FILTER (0x80 | BIO_TYPE_FILTER)
+
+static BIO_METHOD *pcipherbiometh = NULL;
+
+# define BIO_MSG_N(array, stride, n) (*(BIO_MSG *)((char *)(array) + (n)*(stride)))
+
+static int pcipher_sendmmsg(BIO *b, BIO_MSG *msg, size_t stride,
+ size_t num_msg, uint64_t flags,
+ size_t *num_processed)
+{
+ OSSL_QUIC_FAULT *fault;
+ BIO *next = BIO_next(b);
+ ossl_ssize_t ret = 0;
+ BIO_MSG m;
+ size_t i = 0, tmpnump;
+ QUIC_PKT_HDR hdr;
+ PACKET pkt;
+
+ m.data = NULL;
+
+ if (next == NULL)
+ return 0;
+
+ fault = BIO_get_data(b);
+ if (fault == NULL || fault->pciphercb == NULL)
+ return BIO_sendmmsg(next, msg, stride, num_msg, flags, num_processed);
+
+ if (num_msg == 0) {
+ *num_processed = 0;
+ return 1;
+ }
+
+ for (i = 0; i < num_msg; ++i) {
+ m = BIO_MSG_N(msg, stride, i);
+
+ /* Take a copy of the data so that callbacks can modify it */
+ m.data = OPENSSL_memdup(m.data, m.data_len);
+ if (m.data == NULL)
+ return 0;
+
+ if (!PACKET_buf_init(&pkt, m.data, m.data_len))
+ return 0;
+
+ do {
+ if (!ossl_quic_wire_decode_pkt_hdr(&pkt,
+ 0/* TODO(QUIC): Not sure how this should be set*/, 1, &hdr,
+ NULL))
+ goto out;
+
+ /* TODO(QUIC): Resolve const issue here */
+ if (!fault->pciphercb(fault, &hdr, (unsigned char *)hdr.data,
+ hdr.len, fault->pciphercbarg))
+ goto out;
+ } while (PACKET_remaining(&pkt) > 0);
+
+ if (!BIO_sendmmsg(next, &m, stride, 1, flags, &tmpnump)) {
+ *num_processed = i;
+ goto out;
+ }
+
+ OPENSSL_free(m.data);
+ m.data = NULL;
+ }
+
+ *num_processed = i;
+ ret = 1;
+out:
+ if (i > 0)
+ ret = 1;
+ else
+ ret = 0;
+ OPENSSL_free(m.data);
+ return ret;
+}
+
+static long pcipher_ctrl(BIO *b, int cmd, long larg, void *parg)
+{
+ BIO *next = BIO_next(b);
+
+ if (next == NULL)
+ return -1;
+
+ return BIO_ctrl(next, cmd, larg, parg);
+}
+
+static BIO_METHOD *get_bio_method(void)
+{
+ BIO_METHOD *tmp;
+
+ if (pcipherbiometh != NULL)
+ return pcipherbiometh;
+
+ tmp = BIO_meth_new(BIO_TYPE_CIPHER_PACKET_FILTER, "Cipher Packet Filter");
+
+ if (!TEST_ptr(tmp))
+ return NULL;
+
+ if (!TEST_true(BIO_meth_set_sendmmsg(tmp, pcipher_sendmmsg))
+ || !TEST_true(BIO_meth_set_ctrl(tmp, pcipher_ctrl)))
+ goto err;
+
+ pcipherbiometh = tmp;
+ tmp = NULL;
+ err:
+ BIO_meth_free(tmp);
+ return pcipherbiometh;
+}
+
+int ossl_quic_fault_set_packet_cipher_listener(OSSL_QUIC_FAULT *fault,
+ ossl_quic_fault_on_packet_cipher_cb pciphercb,
+ void *pciphercbarg)
+{
+ fault->pciphercb = pciphercb;
+ fault->pciphercbarg = pciphercbarg;
+
+ return 1;
+} \ No newline at end of file
diff --git a/test/helpers/quictestlib.h b/test/helpers/quictestlib.h
index e9514df6f2..fb529b5c1a 100644
--- a/test/helpers/quictestlib.h
+++ b/test/helpers/quictestlib.h
@@ -83,7 +83,7 @@ int ossl_quic_fault_set_handshake_listener(OSSL_QUIC_FAULT *fault,
/*
* Helper function to be called from a handshake_listener callback if it wants
- * to rezie the handshake message (either to add new data to it, or to truncate
+ * to resize the handshake message (either to add new data to it, or to truncate
* it). newlen must include the length of the handshake message header.
*/
int ossl_quic_fault_resize_handshake(OSSL_QUIC_FAULT *fault, size_t newlen);
@@ -134,4 +134,18 @@ int ossl_quic_fault_delete_extension(OSSL_QUIC_FAULT *fault,
* for specific extension types
*/
-/* TODO(QUIC): Add a listener for a datagram here */ \ No newline at end of file
+/*
+ * Enable tests to listen for post-encryption QUIC packets being sent
+ */
+typedef int (*ossl_quic_fault_on_packet_cipher_cb)(OSSL_QUIC_FAULT *fault,
+ /* The parsed packet header */
+ QUIC_PKT_HDR *hdr,
+ /* The packet payload data */
+ unsigned char *buf,
+ /* Length of the payload */
+ size_t len,
+ void *cbarg);
+
+int ossl_quic_fault_set_packet_cipher_listener(OSSL_QUIC_FAULT *fault,
+ ossl_quic_fault_on_packet_cipher_cb pciphercb,
+ void *picphercbarg);