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;
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");
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();
}