diff options
author | Hugo Landau <hlandau@openssl.org> | 2024-01-19 14:52:44 +0000 |
---|---|---|
committer | Hugo Landau <hlandau@openssl.org> | 2024-01-23 14:20:06 +0000 |
commit | 113be15a5ee9aa79a70098e27071c46175cbbb18 (patch) | |
tree | dbe4e9e55e8edd91c4d2b0d033f6596a664bea9b /ssl | |
parent | 2695f7b19b3dba8a89b7081e2427cdf2f66d232f (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.c | 2 | ||||
-rw-r--r-- | ssl/quic/quic_impl.c | 51 | ||||
-rw-r--r-- | ssl/ssl_err.c | 4 | ||||
-rw-r--r-- | ssl/ssl_lib.c | 20 | ||||
-rw-r--r-- | ssl/ssl_local.h | 3 | ||||
-rw-r--r-- | ssl/sslerr.h | 2 |
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 |