summaryrefslogtreecommitdiffstats
path: root/ssl
diff options
context:
space:
mode:
authorHugo Landau <hlandau@openssl.org>2024-01-19 14:52:44 +0000
committerHugo Landau <hlandau@openssl.org>2024-01-23 14:20:06 +0000
commit113be15a5ee9aa79a70098e27071c46175cbbb18 (patch)
treedbe4e9e55e8edd91c4d2b0d033f6596a664bea9b /ssl
parent2695f7b19b3dba8a89b7081e2427cdf2f66d232f (diff)
QUIC APL: Implement optimised FIN API
Reviewed-by: Neil Horman <nhorman@openssl.org> Reviewed-by: Matt Caswell <matt@openssl.org> (Merged from https://github.com/openssl/openssl/pull/23343)
Diffstat (limited to 'ssl')
-rw-r--r--ssl/bio_ssl.c2
-rw-r--r--ssl/quic/quic_impl.c51
-rw-r--r--ssl/ssl_err.c4
-rw-r--r--ssl/ssl_lib.c20
-rw-r--r--ssl/ssl_local.h3
-rw-r--r--ssl/sslerr.h2
6 files changed, 61 insertions, 21 deletions
diff --git a/ssl/bio_ssl.c b/ssl/bio_ssl.c
index 68dd48a5ef..44b05ad27d 100644
--- a/ssl/bio_ssl.c
+++ b/ssl/bio_ssl.c
@@ -174,7 +174,7 @@ static int ssl_write(BIO *b, const char *buf, size_t size, size_t *written)
BIO_clear_retry_flags(b);
- ret = ssl_write_internal(ssl, buf, size, written);
+ ret = ssl_write_internal(ssl, buf, size, 0, written);
switch (SSL_get_error(ssl, ret)) {
case SSL_ERROR_NONE:
diff --git a/ssl/quic/quic_impl.c b/ssl/quic/quic_impl.c
index 5306d6bd40..fecd9525be 100644
--- a/ssl/quic/quic_impl.c
+++ b/ssl/quic/quic_impl.c
@@ -2166,7 +2166,9 @@ int ossl_quic_want(const SSL *s)
*
*/
QUIC_NEEDS_LOCK
-static void quic_post_write(QUIC_XSO *xso, int did_append, int do_tick)
+static void quic_post_write(QUIC_XSO *xso, int did_append,
+ int did_append_all, uint64_t flags,
+ int do_tick)
{
/*
* We have appended at least one byte to the stream.
@@ -2176,6 +2178,9 @@ static void quic_post_write(QUIC_XSO *xso, int did_append, int do_tick)
ossl_quic_stream_map_update_state(ossl_quic_channel_get_qsm(xso->conn->ch),
xso->stream);
+ if (did_append_all && (flags & SSL_WRITE_FLAG_CONCLUDE) != 0)
+ ossl_quic_sstream_fin(xso->stream->sstream);
+
/*
* Try and send.
*
@@ -2192,6 +2197,7 @@ struct quic_write_again_args {
size_t len;
size_t total_written;
int err;
+ uint64_t flags;
};
/*
@@ -2267,7 +2273,8 @@ static int quic_write_again(void *arg)
if (!xso_sstream_append(args->xso, args->buf, args->len, &actual_written))
return -2;
- quic_post_write(args->xso, actual_written > 0, 0);
+ quic_post_write(args->xso, actual_written > 0,
+ args->len == actual_written, args->flags, 0);
args->buf += actual_written;
args->len -= actual_written;
@@ -2283,7 +2290,7 @@ static int quic_write_again(void *arg)
QUIC_NEEDS_LOCK
static int quic_write_blocking(QCTX *ctx, const void *buf, size_t len,
- size_t *written)
+ uint64_t flags, size_t *written)
{
int res;
QUIC_XSO *xso = ctx->xso;
@@ -2297,7 +2304,7 @@ static int quic_write_blocking(QCTX *ctx, const void *buf, size_t len,
return QUIC_RAISE_NON_NORMAL_ERROR(ctx, ERR_R_INTERNAL_ERROR, NULL);
}
- quic_post_write(xso, actual_written > 0, 1);
+ quic_post_write(xso, actual_written > 0, actual_written == len, flags, 1);
if (actual_written == len) {
/* Managed to append everything on the first try. */
@@ -2315,6 +2322,7 @@ static int quic_write_blocking(QCTX *ctx, const void *buf, size_t len,
args.len = len - actual_written;
args.total_written = 0;
args.err = ERR_R_INTERNAL_ERROR;
+ args.flags = flags;
res = block_until_pred(xso->conn, quic_write_again, &args, 0);
if (res <= 0) {
@@ -2353,7 +2361,8 @@ static void aon_write_finish(QUIC_XSO *xso)
QUIC_NEEDS_LOCK
static int quic_write_nonblocking_aon(QCTX *ctx, const void *buf,
- size_t len, size_t *written)
+ size_t len, uint64_t flags,
+ size_t *written)
{
QUIC_XSO *xso = ctx->xso;
const void *actual_buf;
@@ -2390,7 +2399,8 @@ static int quic_write_nonblocking_aon(QCTX *ctx, const void *buf,
return QUIC_RAISE_NON_NORMAL_ERROR(ctx, ERR_R_INTERNAL_ERROR, NULL);
}
- quic_post_write(xso, actual_written > 0, 1);
+ quic_post_write(xso, actual_written > 0, actual_written == actual_len,
+ flags, 1);
if (actual_written == actual_len) {
/* We have sent everything. */
@@ -2440,7 +2450,7 @@ static int quic_write_nonblocking_aon(QCTX *ctx, const void *buf,
QUIC_NEEDS_LOCK
static int quic_write_nonblocking_epw(QCTX *ctx, const void *buf, size_t len,
- size_t *written)
+ uint64_t flags, size_t *written)
{
QUIC_XSO *xso = ctx->xso;
@@ -2451,7 +2461,7 @@ static int quic_write_nonblocking_epw(QCTX *ctx, const void *buf, size_t len,
return QUIC_RAISE_NON_NORMAL_ERROR(ctx, ERR_R_INTERNAL_ERROR, NULL);
}
- quic_post_write(xso, *written > 0, 1);
+ quic_post_write(xso, *written > 0, *written == len, flags, 1);
return 1;
}
@@ -2498,7 +2508,8 @@ static int quic_validate_for_write(QUIC_XSO *xso, int *err)
}
QUIC_TAKES_LOCK
-int ossl_quic_write(SSL *s, const void *buf, size_t len, size_t *written)
+int ossl_quic_write_flags(SSL *s, const void *buf, size_t len,
+ uint64_t flags, size_t *written)
{
int ret;
QCTX ctx;
@@ -2511,6 +2522,11 @@ int ossl_quic_write(SSL *s, const void *buf, size_t len, size_t *written)
partial_write = ((ctx.xso->ssl_mode & SSL_MODE_ENABLE_PARTIAL_WRITE) != 0);
+ if ((flags & ~SSL_WRITE_FLAG_CONCLUDE) != 0) {
+ ret = QUIC_RAISE_NON_NORMAL_ERROR(&ctx, SSL_R_UNSUPPORTED_WRITE_FLAG, NULL);
+ goto out;
+ }
+
if (!quic_mutation_allowed(ctx.qc, /*req_active=*/0)) {
ret = QUIC_RAISE_NON_NORMAL_ERROR(&ctx, SSL_R_PROTOCOL_IS_SHUTDOWN, NULL);
goto out;
@@ -2532,22 +2548,31 @@ int ossl_quic_write(SSL *s, const void *buf, size_t len, size_t *written)
}
if (len == 0) {
+ if ((flags & SSL_WRITE_FLAG_CONCLUDE) != 0)
+ quic_post_write(ctx.xso, 0, 1, flags, 1);
+
ret = 1;
goto out;
}
if (xso_blocking_mode(ctx.xso))
- ret = quic_write_blocking(&ctx, buf, len, written);
+ ret = quic_write_blocking(&ctx, buf, len, flags, written);
else if (partial_write)
- ret = quic_write_nonblocking_epw(&ctx, buf, len, written);
+ ret = quic_write_nonblocking_epw(&ctx, buf, len, flags, written);
else
- ret = quic_write_nonblocking_aon(&ctx, buf, len, written);
+ ret = quic_write_nonblocking_aon(&ctx, buf, len, flags, written);
out:
quic_unlock(ctx.qc);
return ret;
}
+QUIC_TAKES_LOCK
+int ossl_quic_write(SSL *s, const void *buf, size_t len, size_t *written)
+{
+ return ossl_quic_write_flags(s, buf, len, 0, written);
+}
+
/*
* SSL_read
* --------
@@ -2876,7 +2901,7 @@ int ossl_quic_conn_stream_conclude(SSL *s)
}
ossl_quic_sstream_fin(qs->sstream);
- quic_post_write(ctx.xso, 1, 1);
+ quic_post_write(ctx.xso, 1, 0, 0, 1);
quic_unlock(ctx.qc);
return 1;
}
diff --git a/ssl/ssl_err.c b/ssl/ssl_err.c
index 1cda4a0aef..41af278a49 100644
--- a/ssl/ssl_err.c
+++ b/ssl/ssl_err.c
@@ -1,6 +1,6 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -572,6 +572,8 @@ static const ERR_STRING_DATA SSL_str_reasons[] = {
"unsupported ssl version"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNSUPPORTED_STATUS_TYPE),
"unsupported status type"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNSUPPORTED_WRITE_FLAG),
+ "unsupported write flag"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_USE_SRTP_NOT_NEGOTIATED),
"use srtp not negotiated"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_VERSION_TOO_HIGH), "version too high"},
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index 5c8a780c19..52e1fe4486 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -2512,13 +2512,14 @@ int SSL_peek_ex(SSL *s, void *buf, size_t num, size_t *readbytes)
return ret;
}
-int ssl_write_internal(SSL *s, const void *buf, size_t num, size_t *written)
+int ssl_write_internal(SSL *s, const void *buf, size_t num,
+ uint64_t flags, size_t *written)
{
SSL_CONNECTION *sc = SSL_CONNECTION_FROM_SSL(s);
#ifndef OPENSSL_NO_QUIC
if (IS_QUIC(s))
- return s->method->ssl_write(s, buf, num, written);
+ return ossl_quic_write_flags(s, buf, num, flags, written);
#endif
if (sc == NULL)
@@ -2535,6 +2536,11 @@ int ssl_write_internal(SSL *s, const void *buf, size_t num, size_t *written)
return -1;
}
+ if (flags != 0) {
+ ERR_raise(ERR_LIB_SSL, SSL_R_UNSUPPORTED_WRITE_FLAG);
+ return -1;
+ }
+
if (sc->early_data_state == SSL_EARLY_DATA_CONNECT_RETRY
|| sc->early_data_state == SSL_EARLY_DATA_ACCEPT_RETRY
|| sc->early_data_state == SSL_EARLY_DATA_READ_RETRY) {
@@ -2640,7 +2646,7 @@ int SSL_write(SSL *s, const void *buf, int num)
return -1;
}
- ret = ssl_write_internal(s, buf, (size_t)num, &written);
+ ret = ssl_write_internal(s, buf, (size_t)num, 0, &written);
/*
* The cast is safe here because ret should be <= INT_MAX because num is
@@ -2654,7 +2660,13 @@ int SSL_write(SSL *s, const void *buf, int num)
int SSL_write_ex(SSL *s, const void *buf, size_t num, size_t *written)
{
- int ret = ssl_write_internal(s, buf, num, written);
+ return SSL_write_ex2(s, buf, num, 0, written);
+}
+
+int SSL_write_ex2(SSL *s, const void *buf, size_t num, uint64_t flags,
+ size_t *written)
+{
+ int ret = ssl_write_internal(s, buf, num, flags, written);
if (ret < 0)
ret = 0;
diff --git a/ssl/ssl_local.h b/ssl/ssl_local.h
index aeb0036d3c..8e69760b60 100644
--- a/ssl/ssl_local.h
+++ b/ssl/ssl_local.h
@@ -2463,7 +2463,8 @@ void ossl_ssl_connection_free(SSL *ssl);
__owur int ossl_ssl_connection_reset(SSL *ssl);
__owur int ssl_read_internal(SSL *s, void *buf, size_t num, size_t *readbytes);
-__owur int ssl_write_internal(SSL *s, const void *buf, size_t num, size_t *written);
+__owur int ssl_write_internal(SSL *s, const void *buf, size_t num,
+ uint64_t flags, size_t *written);
int ssl_clear_bad_session(SSL_CONNECTION *s);
__owur CERT *ssl_cert_new(size_t ssl_pkey_num);
__owur CERT *ssl_cert_dup(CERT *cert);
diff --git a/ssl/sslerr.h b/ssl/sslerr.h
index f28230f087..7d2bbd6c4e 100644
--- a/ssl/sslerr.h
+++ b/ssl/sslerr.h
@@ -1,6 +1,6 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 2020-2023 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2020-2024 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy