B<SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION> allows initial connections
and renegotiation between OpenSSL and unpatched clients or servers.
+=head2 Applicability of options to QUIC connections and streams
+
+These options apply to SSL objects referencing a QUIC connection:
+
+=over 4
+
+=item SSL_OP_ALLOW_NO_DHE_KEX
+
+=item SSL_OP_NO_TX_CERTIFICATE_COMPRESSION
+
+=item SSL_OP_NO_RX_CERTIFICATE_COMPRESSION
+
+=item SSL_OP_NO_TICKET
+
+=item SSL_OP_PRIORITIZE_CHACHA
+
+=back
+
+Other options do not have an effect and will be ignored.
+
+These options apply to SSL objects referencing a QUIC stream:
+
+=over 4
+
+=item SSL_OP_CLEANSE_PLAINTEXT
+
+=back
+
+Other options do not have an effect and will be ignored.
+
+If an SSL object is a QUIC connection object with a default stream attached,
+only the stream-relevant options are applied. If it is a QUIC connection
+without a default stream, the stream-relevant options are ignored.
+
+Connection and stream relevant options are initialized from the options
+set on SSL_CTX before the connection or stream objects are created.
+
=head1 RETURN VALUES
SSL_CTX_set_options() and SSL_set_options() return the new options bit-mask
uint64_t offset;
/* Is head locked ? */
int head_locked;
+ /* Cleanse data on release? */
+ int cleanse;
} SFRAME_LIST;
/*
__owur int ossl_quic_get_key_update_type(const SSL *s);
__owur int ossl_quic_num_ciphers(void);
__owur const SSL_CIPHER *ossl_quic_get_cipher(unsigned int u);
+__owur int ossl_quic_set_ssl_op(SSL *ssl, uint64_t op);
int ossl_quic_renegotiate_check(SSL *ssl, int initok);
typedef struct quic_conn_st QUIC_CONNECTION;
* than currently occupied.
*/
int ossl_quic_rstream_resize_rbuf(QUIC_RSTREAM *qrs, size_t rbuf_size);
+
+/*
+ * Sets flag to cleanse the buffered data when user reads it.
+ */
+void ossl_quic_rstream_set_cleanse(QUIC_RSTREAM *qrs, int cleanse);
# endif
#endif
}
static ossl_inline void ring_buf_cpop_range(struct ring_buf *r,
- uint64_t start, uint64_t end)
+ uint64_t start, uint64_t end,
+ int cleanse)
{
assert(end >= start);
if (start > r->ctail_offset)
return;
+ if (cleanse && r->alloc > 0 && end > r->ctail_offset) {
+ size_t idx = r->ctail_offset % r->alloc;
+ uint64_t cleanse_end = end + 1;
+ size_t l;
+
+ if (cleanse_end > r->head_offset)
+ cleanse_end = r->head_offset;
+ l = (size_t)(cleanse_end - r->ctail_offset);
+ if (l > r->alloc - idx) {
+ OPENSSL_cleanse((unsigned char *)r->start + idx, r->alloc - idx);
+ l -= r->alloc - idx;
+ idx = 0;
+ }
+ if (l > 0)
+ OPENSSL_cleanse((unsigned char *)r->start + idx, l);
+ }
+
r->ctail_offset = end + 1;
/* Allow culling unpushed data */
if (r->head_offset < r->ctail_offset)
if (can_send && (qs->sstream = ossl_quic_sstream_new(INIT_APP_BUF_LEN)) == NULL)
goto err;
- if (can_recv && (qs->rstream = ossl_quic_rstream_new(NULL, NULL, 0)) == NULL)
- goto err;
+ if (can_recv) {
+ if ((qs->rstream = ossl_quic_rstream_new(NULL, NULL, 0)) == NULL)
+ goto err;
+ ossl_quic_rstream_set_cleanse(qs->rstream,
+ (ch->tls->ctx->options
+ & SSL_OP_CLEANSE_PLAINTEXT) != 0);
+ }
/* TXFC */
if (!ossl_quic_txfc_init(&qs->txfc, &ch->conn_txfc))
return NULL;
}
+int ossl_quic_set_ssl_op(SSL *ssl, uint64_t op)
+{
+ QCTX ctx;
+
+ if (!expect_quic_with_stream_lock(ssl, /*remote_init=*/-1, &ctx))
+ return 0;
+
+ if (ctx.xso->stream == NULL || ctx.xso->stream->rstream == NULL)
+ goto out;
+
+ ossl_quic_rstream_set_cleanse(ctx.xso->stream->rstream,
+ (op & SSL_OP_CLEANSE_PLAINTEXT) != 0);
+
+ out:
+ quic_unlock(ctx.qc);
+ return 1;
+}
+
/*
* Internal Testing APIs
* =====================
if (drop && offset != 0) {
ret = ossl_sframe_list_drop_frames(&qrs->fl, offset);
- ring_buf_cpop_range(&qrs->rbuf, 0, offset - 1);
+ ring_buf_cpop_range(&qrs->rbuf, 0, offset - 1, qrs->fl.cleanse);
}
if (ret) {
return 0;
if (offset > 0)
- ring_buf_cpop_range(&qrs->rbuf, 0, offset - 1);
+ ring_buf_cpop_range(&qrs->rbuf, 0, offset - 1, qrs->fl.cleanse);
if (qrs->rxfc != NULL) {
OSSL_TIME rtt = get_rtt(qrs);
return 1;
}
+
+void ossl_quic_rstream_set_cleanse(QUIC_RSTREAM *qrs, int cleanse)
+{
+ qrs->fl.cleanse = cleanse;
+}
static void stream_frame_free(SFRAME_LIST *fl, STREAM_FRAME *sf)
{
+ if (fl->cleanse && sf->data != NULL)
+ OPENSSL_cleanse((unsigned char *)sf->data,
+ (size_t)(sf->range.end - sf->range.start));
ossl_qrx_pkt_release(sf->pkt);
OPENSSL_free(sf);
}
/* data did not fit */
return 0;
+ if (fl->cleanse)
+ OPENSSL_cleanse((unsigned char *)sf->data,
+ (size_t)(sf->range.end - sf->range.start));
+
/* release the packet */
sf->data = NULL;
ossl_qrx_pkt_release(sf->pkt);
* can only cull contiguous areas at the start of the ring buffer anyway.
*/
if (h != NULL)
- ring_buf_cpop_range(&qss->ring_buf, h->range.start, h->range.end);
+ ring_buf_cpop_range(&qss->ring_buf, h->range.start, h->range.end, 0);
}
int ossl_quic_sstream_set_buffer_size(QUIC_SSTREAM *qss, size_t num_bytes)
uint64_t SSL_set_options(SSL *s, uint64_t op)
{
- SSL_CONNECTION *sc = SSL_CONNECTION_FROM_SSL(s);
+ SSL_CONNECTION *sc;
OSSL_PARAM options[2], *opts = options;
- if (sc == NULL)
+#ifndef OPENSSL_NO_QUIC
+ if (IS_QUIC(s) && ossl_quic_set_ssl_op(s, op))
+ /* Handled by QUIC, return as set */
+ return op;
+#endif
+
+ sc = SSL_CONNECTION_FROM_SSL(s);
+ if (sc == NULL)
return 0;
sc->options |= op;
|| !TEST_ptr(rstream = ossl_quic_rstream_new(NULL, NULL, 0)))
goto err;
+ if (idx % 3 == 0)
+ ossl_quic_rstream_set_cleanse(rstream, 1);
+
for (i = 0; i < data_size; ++i)
bulk_data[i] = (unsigned char)(test_random() & 0xFF);
}
if (!TEST_size_t_ge(readbytes, queued_min - read_off)
|| !TEST_size_t_le(readbytes + read_off, data_size)
- || !TEST_mem_eq(read_buf, readbytes, bulk_data + read_off,
- readbytes))
+ || (idx % 3 != 0
+ && !TEST_mem_eq(read_buf, readbytes, bulk_data + read_off,
+ readbytes)))
goto err;
read_off += readbytes;
queued_min = read_off;
TEST_info("Total read bytes: %zu Fin rcvd: %d", read_off, fin);
+ if (idx % 3 == 0)
+ for (i = 0; i < read_off; i++)
+ if (!TEST_uchar_eq(bulk_data[i], 0))
+ goto err;
+
if (read_off == data_size && fin_set && !fin) {
/* We might still receive the final empty frame */
if (idx % 2 == 0) {
ret = 1;
err:
+ ossl_quic_rstream_free(rstream);
OPENSSL_free(bulk_data);
OPENSSL_free(read_buf);
- ossl_quic_rstream_free(rstream);
return ret;
}