summaryrefslogtreecommitdiff
path: root/ssl
diff options
context:
space:
mode:
authorMatt Caswell <matt@openssl.org>2022-11-29 16:04:23 +0000
committerHugo Landau <hlandau@openssl.org>2023-02-22 05:33:23 +0000
commit14e314093943ffd89633746179c2c8f0b5c631a4 (patch)
tree53740fcd9d9ec7b3414757138b077770cbc0496a /ssl
parentfdd4716dd61e3e8fce77c04987e9dc5df7be7d9d (diff)
downloadopenssl-new-14e314093943ffd89633746179c2c8f0b5c631a4.tar.gz
Add the ability to mutate QUIC packets before they are written
We add callbacks so that QUIC packets can be modified by the test framework before they are encrypted and written to the network. This enables us to simulate badly behaving endpoints. 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 'ssl')
-rw-r--r--ssl/quic/quic_channel.c13
-rw-r--r--ssl/quic/quic_record_tx.c65
-rw-r--r--ssl/quic/quic_tserver.c10
3 files changed, 72 insertions, 16 deletions
diff --git a/ssl/quic/quic_channel.c b/ssl/quic/quic_channel.c
index bffd0d3244..6a0cc6d004 100644
--- a/ssl/quic/quic_channel.c
+++ b/ssl/quic/quic_channel.c
@@ -347,6 +347,19 @@ void ossl_quic_channel_free(QUIC_CHANNEL *ch)
OPENSSL_free(ch);
}
+/* Set mutator callbacks for test framework support */
+int ossl_quic_channel_set_mutator(QUIC_CHANNEL *ch,
+ ossl_mutate_packet_cb mutatecb,
+ ossl_finish_mutate_cb finishmutatecb,
+ void *mutatearg)
+{
+ if (ch->qtx == NULL)
+ return 0;
+
+ ossl_qtx_set_mutator(ch->qtx, mutatecb, finishmutatecb, mutatearg);
+ return 1;
+}
+
int ossl_quic_channel_get_peer_addr(QUIC_CHANNEL *ch, BIO_ADDR *peer_addr)
{
*peer_addr = ch->cur_peer_addr;
diff --git a/ssl/quic/quic_record_tx.c b/ssl/quic/quic_record_tx.c
index dddb29663c..28ebc436bb 100644
--- a/ssl/quic/quic_record_tx.c
+++ b/ssl/quic/quic_record_tx.c
@@ -90,6 +90,10 @@ struct ossl_qtx_st {
* confidentiality limit.
*/
uint64_t epoch_pkt_count;
+
+ ossl_mutate_packet_cb mutatecb;
+ ossl_finish_mutate_cb finishmutatecb;
+ void *mutatearg;
};
/* Instantiates a new QTX. */
@@ -141,6 +145,15 @@ void ossl_qtx_free(OSSL_QTX *qtx)
OPENSSL_free(qtx);
}
+/* Set mutator callbacks for test framework support */
+void ossl_qtx_set_mutator(OSSL_QTX *qtx, ossl_mutate_packet_cb mutatecb,
+ ossl_finish_mutate_cb finishmutatecb, void *mutatearg)
+{
+ qtx->mutatecb = mutatecb;
+ qtx->finishmutatecb = finishmutatecb;
+ qtx->mutatearg = mutatearg;
+}
+
int ossl_qtx_provide_secret(OSSL_QTX *qtx,
uint32_t enc_level,
uint32_t suite_id,
@@ -414,7 +427,7 @@ int ossl_qtx_calculate_plaintext_payload_len(OSSL_QTX *qtx, uint32_t enc_level,
*/
#define QTX_FAIL_INSUFFICIENT_LEN (-2)
-static int qtx_write_hdr(OSSL_QTX *qtx, const OSSL_QTX_PKT *pkt, TXE *txe,
+static int qtx_write_hdr(OSSL_QTX *qtx, const QUIC_PKT_HDR *hdr, TXE *txe,
QUIC_PKT_HDR_PTRS *ptrs)
{
WPACKET wpkt;
@@ -424,8 +437,8 @@ static int qtx_write_hdr(OSSL_QTX *qtx, const OSSL_QTX_PKT *pkt, TXE *txe,
txe->alloc_len - txe->data_len, 0))
return 0;
- if (!ossl_quic_wire_encode_pkt_hdr(&wpkt, pkt->hdr->dst_conn_id.id_len,
- pkt->hdr, ptrs)
+ if (!ossl_quic_wire_encode_pkt_hdr(&wpkt, hdr->dst_conn_id.id_len,
+ hdr, ptrs)
|| !WPACKET_get_total_written(&wpkt, &l)) {
WPACKET_finish(&wpkt);
return 0;
@@ -534,6 +547,9 @@ static int qtx_write(OSSL_QTX *qtx, const OSSL_QTX_PKT *pkt, TXE *txe,
QUIC_PKT_HDR_PTRS ptrs;
unsigned char *hdr_start;
OSSL_QRL_ENC_LEVEL *el = NULL;
+ QUIC_PKT_HDR *hdr;
+ const OSSL_QTX_IOVEC *iovec;
+ size_t num_iovec;
/*
* Determine if the packet needs encryption and the minimum conceivable
@@ -558,8 +574,25 @@ static int qtx_write(OSSL_QTX *qtx, const OSSL_QTX_PKT *pkt, TXE *txe,
goto err;
}
+ /* Set some fields in the header we are responsible for. */
+ if (pkt->hdr->type == QUIC_PKT_TYPE_1RTT)
+ pkt->hdr->key_phase = (unsigned char)(el->key_epoch & 1);
+
+ /* If we are running tests then mutate_packet may be non NULL */
+ if (qtx->mutatecb != NULL) {
+ if (!qtx->mutatecb(pkt->hdr, pkt->iovec, pkt->num_iovec, &hdr,
+ &iovec, &num_iovec, qtx->mutatearg)) {
+ ret = QTX_FAIL_GENERIC;
+ goto err;
+ }
+ } else {
+ hdr = pkt->hdr;
+ iovec = pkt->iovec;
+ num_iovec = pkt->num_iovec;
+ }
+
/* Walk the iovecs to determine actual input payload length. */
- iovec_cur_init(&cur, pkt->iovec, pkt->num_iovec);
+ iovec_cur_init(&cur, iovec, num_iovec);
if (cur.bytes_remaining == 0) {
/* No zero-length payloads allowed. */
@@ -573,10 +606,10 @@ static int qtx_write(OSSL_QTX *qtx, const OSSL_QTX_PKT *pkt, TXE *txe,
: cur.bytes_remaining;
/* Determine header length. */
- pkt->hdr->data = NULL;
- pkt->hdr->len = payload_len;
- pred_hdr_len = ossl_quic_wire_get_encoded_pkt_hdr_len(pkt->hdr->dst_conn_id.id_len,
- pkt->hdr);
+ hdr->data = NULL;
+ hdr->len = payload_len;
+ pred_hdr_len = ossl_quic_wire_get_encoded_pkt_hdr_len(hdr->dst_conn_id.id_len,
+ hdr);
if (pred_hdr_len == 0) {
ret = QTX_FAIL_GENERIC;
goto err;
@@ -590,14 +623,10 @@ static int qtx_write(OSSL_QTX *qtx, const OSSL_QTX_PKT *pkt, TXE *txe,
goto err;
}
- /* Set some fields in the header we are responsible for. */
- if (pkt->hdr->type == QUIC_PKT_TYPE_1RTT)
- pkt->hdr->key_phase = (unsigned char)(el->key_epoch & 1);
-
- if (ossl_quic_pkt_type_has_pn(pkt->hdr->type)) {
+ if (ossl_quic_pkt_type_has_pn(hdr->type)) {
if (!ossl_quic_wire_encode_pkt_hdr_pn(pkt->pn,
- pkt->hdr->pn,
- pkt->hdr->pn_len)) {
+ hdr->pn,
+ hdr->pn_len)) {
ret = QTX_FAIL_GENERIC;
goto err;
}
@@ -605,7 +634,7 @@ static int qtx_write(OSSL_QTX *qtx, const OSSL_QTX_PKT *pkt, TXE *txe,
/* Append the header to the TXE. */
hdr_start = txe_data(txe) + txe->data_len;
- if (!qtx_write_hdr(qtx, pkt, txe, &ptrs)) {
+ if (!qtx_write_hdr(qtx, hdr, txe, &ptrs)) {
ret = QTX_FAIL_GENERIC;
goto err;
}
@@ -638,6 +667,8 @@ static int qtx_write(OSSL_QTX *qtx, const OSSL_QTX_PKT *pkt, TXE *txe,
assert(txe->data_len - orig_data_len == pkt_len);
}
+ if (qtx->finishmutatecb != NULL)
+ qtx->finishmutatecb(qtx->mutatearg);
return 1;
err:
@@ -646,6 +677,8 @@ err:
* TXE.
*/
txe->data_len = orig_data_len;
+ if (qtx->finishmutatecb != NULL)
+ qtx->finishmutatecb(qtx->mutatearg);
return ret;
}
diff --git a/ssl/quic/quic_tserver.c b/ssl/quic/quic_tserver.c
index 5a03aa5327..2b5f04ac5a 100644
--- a/ssl/quic/quic_tserver.c
+++ b/ssl/quic/quic_tserver.c
@@ -122,6 +122,16 @@ void ossl_quic_tserver_free(QUIC_TSERVER *srv)
OPENSSL_free(srv);
}
+/* Set mutator callbacks for test framework support */
+int ossl_quic_tserver_set_mutator(QUIC_TSERVER *srv,
+ ossl_mutate_packet_cb mutatecb,
+ ossl_finish_mutate_cb finishmutatecb,
+ void *mutatearg)
+{
+ return ossl_quic_channel_set_mutator(srv->ch, mutatecb, finishmutatecb,
+ mutatearg);
+}
+
int ossl_quic_tserver_tick(QUIC_TSERVER *srv)
{
ossl_quic_reactor_tick(ossl_quic_channel_get_reactor(srv->ch));