mirror of
https://github.com/openssl/openssl.git
synced 2024-12-14 12:34:02 +08:00
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)
This commit is contained in:
parent
da81f1e563
commit
de60deb258
@ -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))
|
||||
goto err;
|
||||
tserver_args.net_rbio = bio2;
|
||||
tserver_args.net_wbio = bio2;
|
||||
|
||||
if (!TEST_ptr(*qtserv = ossl_quic_tserver_new(&tserver_args, certfile,
|
||||
keyfile))) {
|
||||
/* We hold 2 refs to bio2 at the moment */
|
||||
BIO_free(bio2);
|
||||
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;
|
||||
|
||||
(*fault)->qtserv = *qtserv;
|
||||
}
|
||||
|
||||
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 = sbio;
|
||||
tserver_args.net_wbio = fisbio;
|
||||
|
||||
if (!TEST_ptr(*qtserv = ossl_quic_tserver_new(&tserver_args, certfile,
|
||||
keyfile)))
|
||||
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;
|
||||
}
|
@ -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 */
|
||||
/*
|
||||
* 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);
|
||||
|
Loading…
Reference in New Issue
Block a user