summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/internal/quic_tls.h15
-rw-r--r--ssl/quic/quic_channel.c31
-rw-r--r--ssl/quic/quic_tls.c33
3 files changed, 52 insertions, 27 deletions
diff --git a/include/internal/quic_tls.h b/include/internal/quic_tls.h
index 2d6007e79f..133e247c26 100644
--- a/include/internal/quic_tls.h
+++ b/include/internal/quic_tls.h
@@ -32,9 +32,18 @@ typedef struct quic_tls_args_st {
int (*crypto_send_cb)(const unsigned char *buf, size_t buf_len,
size_t *consumed, void *arg);
void *crypto_send_cb_arg;
- int (*crypto_recv_cb)(unsigned char *buf, size_t buf_len,
- size_t *bytes_read, void *arg);
- void *crypto_recv_cb_arg;
+
+ /*
+ * Call to receive crypto stream data. A pointer to the underlying buffer
+ * is provided, and subsequently released to avoid unnecessary copying of
+ * data.
+ */
+ int (*crypto_recv_rcd_cb)(const unsigned char **buf, size_t *bytes_read,
+ void *arg);
+ void *crypto_recv_rcd_cb_arg;
+ int (*crypto_release_rcd_cb)(size_t bytes_read, void *arg);
+ void *crypto_release_rcd_cb_arg;
+
/* Called when a traffic secret is available for a given encryption level. */
int (*yield_secret_cb)(uint32_t enc_level, int direction /* 0=RX, 1=TX */,
diff --git a/ssl/quic/quic_channel.c b/ssl/quic/quic_channel.c
index a873054f90..460a7d77db 100644
--- a/ssl/quic/quic_channel.c
+++ b/ssl/quic/quic_channel.c
@@ -57,8 +57,9 @@ static int ch_on_handshake_yield_secret(uint32_t enc_level, int direction,
const unsigned char *secret,
size_t secret_len,
void *arg);
-static int ch_on_crypto_recv(unsigned char *buf, size_t buf_len,
- size_t *bytes_read, void *arg);
+static int ch_on_crypto_recv_record(const unsigned char **buf,
+ size_t *bytes_read, void *arg);
+static int ch_on_crypto_release_record(size_t bytes_read, void *arg);
static int crypto_ensure_empty(QUIC_RSTREAM *rstream);
static int ch_on_crypto_send(const unsigned char *buf, size_t buf_len,
size_t *consumed, void *arg);
@@ -248,8 +249,10 @@ static int ch_init(QUIC_CHANNEL *ch)
tls_args.s = ch->tls;
tls_args.crypto_send_cb = ch_on_crypto_send;
tls_args.crypto_send_cb_arg = ch;
- tls_args.crypto_recv_cb = ch_on_crypto_recv;
- tls_args.crypto_recv_cb_arg = ch;
+ tls_args.crypto_recv_rcd_cb = ch_on_crypto_recv_record;
+ tls_args.crypto_recv_rcd_cb_arg = ch;
+ tls_args.crypto_release_rcd_cb = ch_on_crypto_release_record;
+ tls_args.crypto_release_rcd_cb_arg = ch;
tls_args.yield_secret_cb = ch_on_handshake_yield_secret;
tls_args.yield_secret_cb_arg = ch;
tls_args.got_transport_params_cb = ch_on_transport_params;
@@ -534,8 +537,8 @@ static int crypto_ensure_empty(QUIC_RSTREAM *rstream)
return avail == 0;
}
-static int ch_on_crypto_recv(unsigned char *buf, size_t buf_len,
- size_t *bytes_read, void *arg)
+static int ch_on_crypto_recv_record(const unsigned char **buf,
+ size_t *bytes_read, void *arg)
{
QUIC_CHANNEL *ch = arg;
QUIC_RSTREAM *rstream;
@@ -569,8 +572,20 @@ static int ch_on_crypto_recv(unsigned char *buf, size_t buf_len,
if (rstream == NULL)
return 0;
- return ossl_quic_rstream_read(rstream, buf, buf_len, bytes_read,
- &is_fin);
+ return ossl_quic_rstream_get_record(rstream, buf, bytes_read,
+ &is_fin);
+}
+
+static int ch_on_crypto_release_record(size_t bytes_read, void *arg)
+{
+ QUIC_CHANNEL *ch = arg;
+ QUIC_RSTREAM *rstream;
+
+ rstream = ch->crypto_recv[ossl_quic_enc_level_to_pn_space(ch->rx_enc_level)];
+ if (rstream == NULL)
+ return 0;
+
+ return ossl_quic_rstream_release_record(rstream, bytes_read);
}
static int ch_on_handshake_yield_secret(uint32_t enc_level, int direction,
diff --git a/ssl/quic/quic_tls.c b/ssl/quic/quic_tls.c
index 088a59f28a..2a7cc03e55 100644
--- a/ssl/quic/quic_tls.c
+++ b/ssl/quic/quic_tls.c
@@ -54,18 +54,12 @@ struct ossl_record_layer_st {
OSSL_RECORD_TEMPLATE template;
/*
- * Temp buffer for storing received data (copied from the stream receive
- * buffer)
- */
- unsigned char recbuf[SSL3_RT_MAX_PLAIN_LENGTH];
-
- /*
* If we hit an error, what alert code should be used
*/
int alert;
- /* Set if recbuf is populated with data */
- unsigned int recread : 1;
+ /* Amount of crypto stream data we have received but not yet released */
+ size_t recread;
/* Callbacks */
OSSL_FUNC_rlayer_msg_callback_fn *msg_callback;
@@ -348,11 +342,11 @@ static int quic_read_record(OSSL_RECORD_LAYER *rl, void **rechandle,
BIO_clear_retry_flags(rl->dummybio);
/*
- * TODO(QUIC): There seems to be an unnecessary copy here. It would be
- * better to send back a ref direct to the underlying buffer
+ * TODO(QUIC): Cast data to const, which should be safe....can read_record
+ * be modified to pass this as const to start with?
*/
- if (!rl->qtls->args.crypto_recv_cb(rl->recbuf, sizeof(rl->recbuf), datalen,
- rl->qtls->args.crypto_recv_cb_arg)) {
+ if (!rl->qtls->args.crypto_recv_rcd_cb((const unsigned char **)data, datalen,
+ rl->qtls->args.crypto_recv_rcd_cb_arg)) {
QUIC_TLS_FATAL(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return OSSL_RECORD_RETURN_FATAL;
}
@@ -365,8 +359,7 @@ static int quic_read_record(OSSL_RECORD_LAYER *rl, void **rechandle,
*rechandle = rl;
*rversion = TLS1_3_VERSION;
*type = SSL3_RT_HANDSHAKE;
- *data = rl->recbuf;
- rl->recread = 1;
+ rl->recread = *datalen;
/* epoch/seq_num are not relevant for TLS */
if (rl->msg_callback != NULL) {
@@ -399,11 +392,18 @@ static int quic_read_record(OSSL_RECORD_LAYER *rl, void **rechandle,
static int quic_release_record(OSSL_RECORD_LAYER *rl, void *rechandle)
{
- if (!ossl_assert(rl->recread == 1) || !ossl_assert(rl == rechandle)) {
+ if (!ossl_assert(rl->recread > 0) || !ossl_assert(rl == rechandle)) {
QUIC_TLS_FATAL(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
+ if (!rl->qtls->args.crypto_release_rcd_cb(rl->recread,
+ rl->qtls->args.crypto_release_rcd_cb_arg)) {
+ QUIC_TLS_FATAL(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ return OSSL_RECORD_RETURN_FATAL;
+ }
+
+
rl->recread = 0;
return 1;
}
@@ -602,7 +602,8 @@ QUIC_TLS *ossl_quic_tls_new(const QUIC_TLS_ARGS *args)
QUIC_TLS *qtls;
if (args->crypto_send_cb == NULL
- || args->crypto_recv_cb == NULL) {
+ || args->crypto_recv_rcd_cb == NULL
+ || args->crypto_release_rcd_cb == NULL) {
ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_NULL_PARAMETER);
return NULL;
}