QUIC APL: Implement optimised FIN API
authorHugo Landau <hlandau@openssl.org>
Fri, 19 Jan 2024 14:52:44 +0000 (14:52 +0000)
committerHugo Landau <hlandau@openssl.org>
Tue, 23 Jan 2024 14:20:06 +0000 (14:20 +0000)
Reviewed-by: Neil Horman <nhorman@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/23343)

crypto/err/openssl.txt
include/internal/quic_ssl.h
include/openssl/sslerr.h
ssl/bio_ssl.c
ssl/quic/quic_impl.c
ssl/ssl_err.c
ssl/ssl_lib.c
ssl/ssl_local.h
ssl/sslerr.h

index 8d302e07d624d9953346d2fe3906eaf3efa13bba..a20c136114bb51427255b0ba534ca7c3552c0917 100644 (file)
@@ -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
index 52d4527c811021e172d3af247181cc834ffc5a02..a9822df7dfeaa5a7e1dce9fe3d5a866489922eca 100644 (file)
@@ -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);
index e1eb9a5692c255efd3f7165c4bb5a4fcfa724496..478d64e29176f24c585892ad787c2b6b54842ad4 100644 (file)
@@ -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
 # 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
index 68dd48a5ef3be899e57cfa5abad93a8ea3c6ce82..44b05ad27db4e975b7362b80ff0b001063005f40 100644 (file)
@@ -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:
index 5306d6bd40a27bebb68efd2dca0302000ac2c192..fecd9525beb233219b66dc7262cedcf0a3264d7d 100644 (file)
@@ -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;
 }
index 1cda4a0aef2555309e7803ca4166565fa113be72..41af278a49532d8863d36b3b52c74c19e879e117 100644 (file)
@@ -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"},
index 5c8a780c19079f2d8b159058cf46777f8fc1777e..52e1fe448637aa14ac21eb0aaf909de1b538b383 100644 (file)
@@ -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;
index aeb0036d3cefb9162301985df2ae7f23e1f42c67..8e69760b601269ab6e75eb792bc6e66b21d2b768 100644 (file)
@@ -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);
index f28230f0875caeefbbb8c5c94b4957ef6af79e81..7d2bbd6c4e637619ade044453b92db7ade613560 100644 (file)
@@ -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