From: Hugo Landau Date: Fri, 19 Jan 2024 14:52:44 +0000 (+0000) Subject: QUIC APL: Implement optimised FIN API X-Git-Tag: openssl-3.3.0-alpha1~274 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=113be15a5ee9aa79a70098e27071c46175cbbb18;p=thirdparty%2Fopenssl.git QUIC APL: Implement optimised FIN API Reviewed-by: Neil Horman Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/23343) --- diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt index 8d302e07d62..a20c136114b 100644 --- a/crypto/err/openssl.txt +++ b/crypto/err/openssl.txt @@ -1,4 +1,4 @@ -# Copyright 1999-2023 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 1999-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 @@ -1638,6 +1638,7 @@ SSL_R_UNSUPPORTED_ELLIPTIC_CURVE:315:unsupported elliptic curve SSL_R_UNSUPPORTED_PROTOCOL:258:unsupported protocol SSL_R_UNSUPPORTED_SSL_VERSION:259:unsupported ssl version SSL_R_UNSUPPORTED_STATUS_TYPE:329:unsupported status type +SSL_R_UNSUPPORTED_WRITE_FLAG:412:unsupported write flag SSL_R_USE_SRTP_NOT_NEGOTIATED:369:use srtp not negotiated SSL_R_VERSION_TOO_HIGH:166:version too high SSL_R_VERSION_TOO_LOW:396:version too low diff --git a/include/internal/quic_ssl.h b/include/internal/quic_ssl.h index 52d4527c811..a9822df7dfe 100644 --- a/include/internal/quic_ssl.h +++ b/include/internal/quic_ssl.h @@ -28,6 +28,8 @@ __owur int ossl_quic_accept(SSL *s); __owur int ossl_quic_connect(SSL *s); __owur int ossl_quic_read(SSL *s, void *buf, size_t len, size_t *readbytes); __owur int ossl_quic_peek(SSL *s, void *buf, size_t len, size_t *readbytes); +__owur int ossl_quic_write_flags(SSL *s, const void *buf, size_t len, + uint64_t flags, size_t *written); __owur int ossl_quic_write(SSL *s, const void *buf, size_t len, size_t *written); __owur long ossl_quic_ctrl(SSL *s, int cmd, long larg, void *parg); __owur long ossl_quic_ctx_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg); diff --git a/include/openssl/sslerr.h b/include/openssl/sslerr.h index e1eb9a5692c..478d64e2917 100644 --- a/include/openssl/sslerr.h +++ b/include/openssl/sslerr.h @@ -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 @@ -350,6 +350,7 @@ # define SSL_R_UNSUPPORTED_PROTOCOL 258 # define SSL_R_UNSUPPORTED_SSL_VERSION 259 # define SSL_R_UNSUPPORTED_STATUS_TYPE 329 +# define SSL_R_UNSUPPORTED_WRITE_FLAG 412 # define SSL_R_USE_SRTP_NOT_NEGOTIATED 369 # define SSL_R_VERSION_TOO_HIGH 166 # define SSL_R_VERSION_TOO_LOW 396 diff --git a/ssl/bio_ssl.c b/ssl/bio_ssl.c index 68dd48a5ef3..44b05ad27db 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 5306d6bd40a..fecd9525beb 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 1cda4a0aef2..41af278a495 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 5c8a780c190..52e1fe44863 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 aeb0036d3ce..8e69760b601 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 f28230f0875..7d2bbd6c4e6 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