QUIC TXP: Don't send STREAM frames until handshake is complete
authorHugo Landau <hlandau@openssl.org>
Mon, 31 Oct 2022 17:39:45 +0000 (17:39 +0000)
committerHugo Landau <hlandau@openssl.org>
Fri, 13 Jan 2023 13:20:12 +0000 (13:20 +0000)
Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/19703)

include/internal/quic_txp.h
ssl/quic/quic_txp.c
test/quic_txp_test.c

index 0ba14d356fa7a22ac5047d3547159e6c07eecec4..6a55b957179ffe967a4e379f947ceacb992ca1bc 100644 (file)
@@ -134,6 +134,14 @@ int ossl_quic_tx_packetiser_set_peer(OSSL_QUIC_TX_PACKETISER *txp,
 int ossl_quic_tx_packetiser_discard_enc_level(OSSL_QUIC_TX_PACKETISER *txp,
                                               uint32_t enc_level);
 
+/*
+ * Informs the TX packetiser that the handshake is complete. The TX packetiser
+ * will not send 1-RTT application data until the handshake is complete,
+ * as the authenticity of the peer is not confirmed until the handshake
+ * complete event occurs.
+ */
+void ossl_quic_tx_packetiser_notify_handshake_complete(OSSL_QUIC_TX_PACKETISER *txp);
+
 /* Asks the TXP to generate a HANDSHAKE_DONE frame in the next 1-RTT packet. */
 void ossl_quic_tx_packetiser_schedule_handshake_done(OSSL_QUIC_TX_PACKETISER *txp);
 
index 5fa9070acd442a50e6fbe1f1696256f324aa7c49..1042c69f447038793b2dbe058cb1988a791df50b 100644 (file)
@@ -59,6 +59,9 @@ struct ossl_quic_tx_packetiser_st {
      */
     unsigned int    want_conn_close         : 1;
 
+    /* Has the handshake been completed? */
+    unsigned int    handshake_complete      : 1;
+
     OSSL_QUIC_FRAME_CONN_CLOSE  conn_close_frame;
 
     /* Internal state - packet assembly. */
@@ -443,6 +446,11 @@ int ossl_quic_tx_packetiser_discard_enc_level(OSSL_QUIC_TX_PACKETISER *txp,
     return 1;
 }
 
+void ossl_quic_tx_packetiser_notify_handshake_complete(OSSL_QUIC_TX_PACKETISER *txp)
+{
+    txp->handshake_complete = 1;
+}
+
 void ossl_quic_tx_packetiser_schedule_handshake_done(OSSL_QUIC_TX_PACKETISER *txp)
 {
     txp->want_handshake_done = 1;
@@ -796,7 +804,7 @@ static int txp_el_pending(OSSL_QUIC_TX_PACKETISER *txp, uint32_t enc_level,
             }
        }
 
-    if (a.allow_stream_rel) {
+    if (a.allow_stream_rel && txp->handshake_complete) {
         QUIC_STREAM_ITER it;
 
         /* If there are any active streams, 0/1-RTT wants to produce a packet.
@@ -1944,7 +1952,7 @@ static int txp_generate_for_el_actual(OSSL_QUIC_TX_PACKETISER *txp,
             goto fatal_err;
 
     /* Stream-specific frames */
-    if (a.allow_stream_rel)
+    if (a.allow_stream_rel && txp->handshake_complete)
         if (!txp_generate_stream_related(txp, &h, pn_space, tpkt, min_ppl,
                                          &have_ack_eliciting,
                                          &tmp_head))
index 54d4a8679fbcc1cd3d7eb5e54b9c089a6d198d32..ab9b943c7ef25d9a585c2953b767297df981fe09 100644 (file)
@@ -227,6 +227,7 @@ err:
 #define OPK_RESET_STREAM            19  /* Mark stream for RESET_STREAM */
 #define OPK_CONN_TXFC_BUMP          20  /* Bump connection TXFC CWM */
 #define OPK_STREAM_TXFC_BUMP        21  /* Bump stream TXFC CWM */
+#define OPK_HANDSHAKE_COMPLETE      22  /* Mark handshake as complete */
 
 struct script_op {
     uint32_t opcode;
@@ -280,6 +281,8 @@ struct script_op {
     { OPK_CONN_TXFC_BUMP, (cwm) },
 #define OP_STREAM_TXFC_BUMP(id, cwm) \
     { OPK_STREAM_TXFC_BUMP, (cwm), (id) },
+#define OP_HANDSHAKE_COMPLETE() \
+    { OPK_HANDSHAKE_COMPLETE },
 
 static int schedule_handshake_done(struct helper *h)
 {
@@ -601,6 +604,7 @@ static int check_stream_9(struct helper *h)
 
 static const struct script_op script_9[] = {
     OP_PROVIDE_SECRET(QUIC_ENC_LEVEL_1RTT, QRL_SUITE_AES128GCM, secret_1)
+    OP_HANDSHAKE_COMPLETE()
     OP_TXP_GENERATE_NONE(TX_PACKETISER_ARCHETYPE_NORMAL)
     OP_STREAM_NEW(42)
     OP_STREAM_SEND(42, stream_9)
@@ -909,6 +913,7 @@ static int check_stream_10d(struct helper *h)
 
 static const struct script_op script_10[] = {
     OP_PROVIDE_SECRET(QUIC_ENC_LEVEL_1RTT, QRL_SUITE_AES128GCM, secret_1)
+    OP_HANDSHAKE_COMPLETE()
     OP_TXP_GENERATE_NONE(TX_PACKETISER_ARCHETYPE_NORMAL)
     OP_STREAM_NEW(42)
     OP_STREAM_NEW(43)
@@ -982,6 +987,7 @@ static int check_stream_12(struct helper *h)
 
 static const struct script_op script_12[] = {
     OP_PROVIDE_SECRET(QUIC_ENC_LEVEL_1RTT, QRL_SUITE_AES128GCM, secret_1)
+    OP_HANDSHAKE_COMPLETE()
     OP_TXP_GENERATE_NONE(TX_PACKETISER_ARCHETYPE_NORMAL)
     OP_STREAM_NEW(42)
     OP_STOP_SENDING(42, 4568)
@@ -1014,6 +1020,7 @@ static ossl_unused int check_stream_13(struct helper *h)
 
 static const struct script_op script_13[] = {
     OP_PROVIDE_SECRET(QUIC_ENC_LEVEL_1RTT, QRL_SUITE_AES128GCM, secret_1)
+    OP_HANDSHAKE_COMPLETE()
     OP_TXP_GENERATE_NONE(TX_PACKETISER_ARCHETYPE_NORMAL)
     OP_STREAM_NEW(42)
     OP_CONN_TXFC_BUMP(8)
@@ -1065,6 +1072,7 @@ static int check_14(struct helper *h)
 
 static const struct script_op script_14[] = {
     OP_PROVIDE_SECRET(QUIC_ENC_LEVEL_1RTT, QRL_SUITE_AES128GCM, secret_1)
+    OP_HANDSHAKE_COMPLETE()
     OP_TXP_GENERATE_NONE(TX_PACKETISER_ARCHETYPE_NORMAL)
     OP_CHECK(gen_conn_close)
     OP_TXP_GENERATE(TX_PACKETISER_ARCHETYPE_NORMAL)
@@ -1399,6 +1407,9 @@ static int run_script(const struct script_op *script)
                 ossl_quic_stream_map_update_state(h.args.qsm, s);
             }
             break;
+        case OPK_HANDSHAKE_COMPLETE:
+            ossl_quic_tx_packetiser_notify_handshake_complete(h.txp);
+            break;
         default:
             TEST_error("bad opcode");
             goto err;