]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
tests/mini-dtls-fragments: #1839 mismatching message_seq
authorAlexander Sosedkin <asosedkin@redhat.com>
Mon, 20 Apr 2026 14:36:08 +0000 (16:36 +0200)
committerAlexander Sosedkin <asosedkin@redhat.com>
Wed, 29 Apr 2026 13:35:02 +0000 (15:35 +0200)
Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
tests/mini-dtls-fragments.c

index 93490bac204e902bbba5ba4bab7f29e978ab8ba7..499a92a92a938797db35846c915e8e18489cdfb3 100644 (file)
@@ -165,7 +165,7 @@ static uint64_t read_u48(const uint8_t *p)
        return seq;
 }
 
-static void test(gnutls_push_func client_push)
+static void test(gnutls_push_func client_push, bool expect_success)
 {
        gnutls_session_t client, server;
        gnutls_certificate_credentials_t ccred, scred;
@@ -218,12 +218,22 @@ static void test(gnutls_push_func client_push)
                        sr = gnutls_handshake(server);
                if (!sr || gnutls_error_is_fatal(sr))
                        sdone = true;
+
+               if (c2s.head == c2s.tail && s2c.head == s2c.tail)
+                       break; /* speed the test up */
        }
 
-       if (cr)
-               fail("client: %s\n", gnutls_strerror(cr));
-       if (sr)
-               fail("server: %s\n", gnutls_strerror(sr));
+       if (expect_success) {
+               if (cr)
+                       fail("client: %s\n", gnutls_strerror(cr));
+               if (sr)
+                       fail("server: %s\n", gnutls_strerror(sr));
+
+       } else {
+               if (cr == 0 && sr == 0)
+                       fail("handshake unexpectedly succeeded: %s / %s\n",
+                            gnutls_strerror(cr), gnutls_strerror(sr));
+       }
 
        success("OK\n");
 
@@ -421,14 +431,44 @@ static ssize_t client_push_split_hello(gnutls_transport_ptr_t tr, const void *b,
        return l;
 }
 
+static ssize_t client_push_split_hello_bad_seq(gnutls_transport_ptr_t tr,
+                                              const void *b, size_t l)
+{
+       /* gnutls wasn't matching on message_seq on merging, see #1839 */
+       static int seq_offset = 0; /* for renumbering follow-up epoch0 ones */
+
+       const uint8_t *data = (const uint8_t *)b;
+       uint8_t *frag1, *frag2;
+       size_t frag1_len, frag2_len;
+
+       /* Pass through anything that isn't an epoch0 ClientHello with body */
+       if (l < 13 + 12 + 1 || /* too short for DTLS record header */
+           data[0] != 22 || /* not a handshake record */
+           data[3] != 0 || data[4] != 0 || /* not epoch 0 */
+           data[13] != 1) /* not ClientHello */
+               return queue_put_renumbered(&c2s, b, l, seq_offset);
+
+       /* epoch0 Client Hello: special treatment of splitting into fragments */
+       split_client_hello(data, l, &frag1, &frag1_len, &frag2, &frag2_len);
+       queue_put(&c2s, frag1, frag1_len);
+       frag2[18]++; /* WRONG, message_seq mismatch must be rejected, #1839 */
+       queue_put(&c2s, frag2, frag2_len);
+       free(frag1);
+       free(frag2);
+       seq_offset++;
+       return l;
+}
+
 void doit(void)
 {
        global_init();
-       test(client_push_normal);
+       test(client_push_normal, true);
        success("malicious reassembly bug exploitation (#1816):\n");
        test_malicious1816();
        success("split client hello smoke-test\n");
-       test(client_push_split_hello);
+       test(client_push_split_hello, true);
+       success("split client hello smoke-test and mangle sequence number\n");
+       test(client_push_split_hello_bad_seq, false);
        gnutls_global_deinit();
 }