summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorjsing <>2021-06-19 15:33:37 +0000
committerjsing <>2021-06-19 15:33:37 +0000
commit941752ee1ae5c1480dafbffcbd9c927d1a91c077 (patch)
tree9a8b0c8db4e435abc56b93924c66965d1867d1bc /src
parent3c569065c92533ff49798d7b9367b0cd770692d4 (diff)
downloadopenbsd-941752ee1ae5c1480dafbffcbd9c927d1a91c077.tar.gz
openbsd-941752ee1ae5c1480dafbffcbd9c927d1a91c077.tar.bz2
openbsd-941752ee1ae5c1480dafbffcbd9c927d1a91c077.zip
Provide the ability to delay/reorder DTLS packets.
Add a test that delays the client CCS, resulting in it arriving after the client Finished message.
Diffstat (limited to 'src')
-rw-r--r--src/regress/lib/libssl/dtls/dtlstest.c161
1 files changed, 147 insertions, 14 deletions
diff --git a/src/regress/lib/libssl/dtls/dtlstest.c b/src/regress/lib/libssl/dtls/dtlstest.c
index 194728e26b..d7f2f4b2de 100644
--- a/src/regress/lib/libssl/dtls/dtlstest.c
+++ b/src/regress/lib/libssl/dtls/dtlstest.c
@@ -1,6 +1,6 @@
1/* $OpenBSD: dtlstest.c,v 1.9 2021/06/18 18:26:38 jsing Exp $ */ 1/* $OpenBSD: dtlstest.c,v 1.10 2021/06/19 15:33:37 jsing Exp $ */
2/* 2/*
3 * Copyright (c) 2020 Joel Sing <jsing@openbsd.org> 3 * Copyright (c) 2020, 2021 Joel Sing <jsing@openbsd.org>
4 * 4 *
5 * Permission to use, copy, modify, and distribute this software for any 5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above 6 * purpose with or without fee is hereby granted, provided that the above
@@ -47,12 +47,19 @@ hexdump(const unsigned char *buf, size_t len)
47 fprintf(stderr, "\n"); 47 fprintf(stderr, "\n");
48} 48}
49 49
50#define BIO_C_DROP_PACKET 1000 50#define BIO_C_DELAY_COUNT 1000
51#define BIO_C_DROP_RANDOM 1001 51#define BIO_C_DELAY_FLUSH 1001
52#define BIO_C_DELAY_PACKET 1002
53#define BIO_C_DROP_PACKET 1003
54#define BIO_C_DROP_RANDOM 1004
52 55
53struct bio_packet_monkey_ctx { 56struct bio_packet_monkey_ctx {
57 unsigned int delay_count;
58 unsigned int delay_mask;
54 unsigned int drop_rand; 59 unsigned int drop_rand;
55 unsigned int drop_mask; 60 unsigned int drop_mask;
61 uint8_t *delayed_msg;
62 size_t delayed_msg_len;
56}; 63};
57 64
58static int 65static int
@@ -80,11 +87,33 @@ bio_packet_monkey_free(BIO *bio)
80 return 1; 87 return 1;
81 88
82 ctx = bio->ptr; 89 ctx = bio->ptr;
90 free(ctx->delayed_msg);
83 free(ctx); 91 free(ctx);
84 92
85 return 1; 93 return 1;
86} 94}
87 95
96static int
97bio_packet_monkey_delay_flush(BIO *bio)
98{
99 struct bio_packet_monkey_ctx *ctx = bio->ptr;
100
101 if (ctx->delayed_msg == NULL)
102 return 1;
103
104 if (debug)
105 fprintf(stderr, "DEBUG: flushing delayed packet...\n");
106 if (debug > 1)
107 hexdump(ctx->delayed_msg, ctx->delayed_msg_len);
108
109 BIO_write(bio->next_bio, ctx->delayed_msg, ctx->delayed_msg_len);
110
111 free(ctx->delayed_msg);
112 ctx->delayed_msg = NULL;
113
114 return BIO_ctrl(bio->next_bio, BIO_CTRL_FLUSH, 0, NULL);
115}
116
88static long 117static long
89bio_packet_monkey_ctrl(BIO *bio, int cmd, long num, void *ptr) 118bio_packet_monkey_ctrl(BIO *bio, int cmd, long num, void *ptr)
90{ 119{
@@ -93,6 +122,21 @@ bio_packet_monkey_ctrl(BIO *bio, int cmd, long num, void *ptr)
93 ctx = bio->ptr; 122 ctx = bio->ptr;
94 123
95 switch (cmd) { 124 switch (cmd) {
125 case BIO_C_DELAY_COUNT:
126 if (num < 1 || num > 31)
127 return 0;
128 ctx->delay_count = num;
129 return 1;
130
131 case BIO_C_DELAY_FLUSH:
132 return bio_packet_monkey_delay_flush(bio);
133
134 case BIO_C_DELAY_PACKET:
135 if (num < 1 || num > 31)
136 return 0;
137 ctx->delay_mask |= 1 << ((unsigned int)num - 1);
138 return 1;
139
96 case BIO_C_DROP_PACKET: 140 case BIO_C_DROP_PACKET:
97 if (num < 1 || num > 31) 141 if (num < 1 || num > 31)
98 return 0; 142 return 0;
@@ -123,6 +167,13 @@ bio_packet_monkey_read(BIO *bio, char *out, int out_len)
123 167
124 ret = BIO_read(bio->next_bio, out, out_len); 168 ret = BIO_read(bio->next_bio, out, out_len);
125 169
170 if (ret > 0) {
171 if (debug)
172 fprintf(stderr, "DEBUG: read packet...\n");
173 if (debug > 1)
174 hexdump(out, ret);
175 }
176
126 BIO_clear_retry_flags(bio); 177 BIO_clear_retry_flags(bio);
127 if (ret <= 0 && BIO_should_retry(bio->next_bio)) 178 if (ret <= 0 && BIO_should_retry(bio->next_bio))
128 BIO_set_retry_read(bio); 179 BIO_set_retry_read(bio);
@@ -134,27 +185,68 @@ static int
134bio_packet_monkey_write(BIO *bio, const char *in, int in_len) 185bio_packet_monkey_write(BIO *bio, const char *in, int in_len)
135{ 186{
136 struct bio_packet_monkey_ctx *ctx = bio->ptr; 187 struct bio_packet_monkey_ctx *ctx = bio->ptr;
137 int drop = 0; 188 const char *label = "writing";
189 int delay = 0, drop = 0;
138 int ret; 190 int ret;
139 191
140 if (ctx == NULL || bio->next_bio == NULL) 192 if (ctx == NULL || bio->next_bio == NULL)
141 return 0; 193 return 0;
142 194
195 if (ctx->delayed_msg != NULL && ctx->delay_count > 0)
196 ctx->delay_count--;
197
198 if (ctx->delayed_msg != NULL && ctx->delay_count == 0) {
199 if (debug)
200 fprintf(stderr, "DEBUG: writing delayed packet...\n");
201 if (debug > 1)
202 hexdump(ctx->delayed_msg, ctx->delayed_msg_len);
203
204 ret = BIO_write(bio->next_bio, ctx->delayed_msg,
205 ctx->delayed_msg_len);
206
207 BIO_clear_retry_flags(bio);
208 if (ret <= 0 && BIO_should_retry(bio->next_bio)) {
209 BIO_set_retry_write(bio);
210 return (ret);
211 }
212
213 free(ctx->delayed_msg);
214 ctx->delayed_msg = NULL;
215 }
216
217 if (ctx->delay_mask > 0) {
218 delay = ctx->delay_mask & 1;
219 ctx->delay_mask >>= 1;
220 }
143 if (ctx->drop_rand > 0) { 221 if (ctx->drop_rand > 0) {
144 drop = arc4random_uniform(ctx->drop_rand) == 0; 222 drop = arc4random_uniform(ctx->drop_rand) == 0;
145 } else if (ctx->drop_mask > 0) { 223 } else if (ctx->drop_mask > 0) {
146 drop = ctx->drop_mask & 1; 224 drop = ctx->drop_mask & 1;
147 ctx->drop_mask >>= 1; 225 ctx->drop_mask >>= 1;
148 } 226 }
149 if (debug) { 227
150 fprintf(stderr, "DEBUG: %s packet...\n", 228 if (delay)
151 drop ? "dropping" : "writing"); 229 label = "delaying";
152 if (debug > 1) 230 if (drop)
153 hexdump(in, in_len); 231 label = "dropping";
154 } 232 if (debug)
233 fprintf(stderr, "DEBUG: %s packet...\n", label);
234 if (debug > 1)
235 hexdump(in, in_len);
236
155 if (drop) 237 if (drop)
156 return in_len; 238 return in_len;
157 239
240 if (delay) {
241 if (ctx->delayed_msg != NULL)
242 return 0;
243 if ((ctx->delayed_msg = calloc(1, in_len)) == NULL)
244 return 0;
245 memcpy(ctx->delayed_msg, in, in_len);
246 ctx->delayed_msg_len = in_len;
247 return in_len;
248 }
249
158 ret = BIO_write(bio->next_bio, in, in_len); 250 ret = BIO_write(bio->next_bio, in, in_len);
159 251
160 BIO_clear_retry_flags(bio); 252 BIO_clear_retry_flags(bio);
@@ -194,6 +286,23 @@ BIO_new_packet_monkey(void)
194} 286}
195 287
196static int 288static int
289BIO_packet_monkey_delay(BIO *bio, int num, int count)
290{
291 if (!BIO_ctrl(bio, BIO_C_DELAY_COUNT, count, NULL))
292 return 0;
293
294 return BIO_ctrl(bio, BIO_C_DELAY_PACKET, num, NULL);
295}
296
297#if 0
298static int
299BIO_packet_monkey_delay_flush(BIO *bio)
300{
301 return BIO_ctrl(bio, BIO_C_DELAY_FLUSH, 0, NULL);
302}
303#endif
304
305static int
197BIO_packet_monkey_drop(BIO *bio, int num) 306BIO_packet_monkey_drop(BIO *bio, int num)
198{ 307{
199 return BIO_ctrl(bio, BIO_C_DROP_PACKET, num, NULL); 308 return BIO_ctrl(bio, BIO_C_DROP_PACKET, num, NULL);
@@ -519,14 +628,22 @@ do_client_server_loop(SSL *client, ssl_func client_func, SSL *server,
519 return client_done && server_done; 628 return client_done && server_done;
520} 629}
521 630
631#define MAX_PACKET_DELAYS 32
522#define MAX_PACKET_DROPS 32 632#define MAX_PACKET_DROPS 32
523 633
634struct dtls_delay {
635 uint8_t packet;
636 uint8_t count;
637};
638
524struct dtls_test { 639struct dtls_test {
525 const unsigned char *desc; 640 const unsigned char *desc;
526 long mtu; 641 long mtu;
527 long ssl_options; 642 long ssl_options;
528 int client_bbio_off; 643 int client_bbio_off;
529 int server_bbio_off; 644 int server_bbio_off;
645 struct dtls_delay client_delays[MAX_PACKET_DELAYS];
646 struct dtls_delay server_delays[MAX_PACKET_DELAYS];
530 uint8_t client_drops[MAX_PACKET_DROPS]; 647 uint8_t client_drops[MAX_PACKET_DROPS];
531 uint8_t server_drops[MAX_PACKET_DROPS]; 648 uint8_t server_drops[MAX_PACKET_DROPS];
532}; 649};
@@ -621,12 +738,20 @@ static const struct dtls_test dtls_tests[] = {
621 .client_bbio_off = 1, 738 .client_bbio_off = 1,
622 .client_drops = { 4 }, 739 .client_drops = { 4 },
623 }, 740 },
741 {
742 /* Send CCS after client Finished. */
743 .desc = "DTLS with delayed client CCS",
744 .ssl_options = 0,
745 .client_bbio_off = 1,
746 .client_delays = { { 3, 2 } },
747 },
624}; 748};
625 749
626#define N_DTLS_TESTS (sizeof(dtls_tests) / sizeof(*dtls_tests)) 750#define N_DTLS_TESTS (sizeof(dtls_tests) / sizeof(*dtls_tests))
627 751
628static void 752static void
629dtlstest_packet_monkey(SSL *ssl, const uint8_t drops[]) 753dtlstest_packet_monkey(SSL *ssl, const struct dtls_delay delays[],
754 const uint8_t drops[])
630{ 755{
631 BIO *bio_monkey; 756 BIO *bio_monkey;
632 BIO *bio; 757 BIO *bio;
@@ -635,6 +760,14 @@ dtlstest_packet_monkey(SSL *ssl, const uint8_t drops[])
635 if ((bio_monkey = BIO_new_packet_monkey()) == NULL) 760 if ((bio_monkey = BIO_new_packet_monkey()) == NULL)
636 errx(1, "packet monkey"); 761 errx(1, "packet monkey");
637 762
763 for (i = 0; i < MAX_PACKET_DELAYS; i++) {
764 if (delays[i].packet == 0)
765 break;
766 if (!BIO_packet_monkey_delay(bio_monkey, delays[i].packet,
767 delays[i].count))
768 errx(1, "delay failure");
769 }
770
638 for (i = 0; i < MAX_PACKET_DROPS; i++) { 771 for (i = 0; i < MAX_PACKET_DROPS; i++) {
639 if (drops[i] == 0) 772 if (drops[i] == 0)
640 break; 773 break;
@@ -676,8 +809,8 @@ dtlstest(const struct dtls_test *dt)
676 if (dt->server_bbio_off) 809 if (dt->server_bbio_off)
677 SSL_set_info_callback(server, dtls_info_callback); 810 SSL_set_info_callback(server, dtls_info_callback);
678 811
679 dtlstest_packet_monkey(client, dt->client_drops); 812 dtlstest_packet_monkey(client, dt->client_delays, dt->client_drops);
680 dtlstest_packet_monkey(server, dt->server_drops); 813 dtlstest_packet_monkey(server, dt->server_delays, dt->server_drops);
681 814
682 pfd[0].fd = client_sock; 815 pfd[0].fd = client_sock;
683 pfd[0].events = POLLOUT; 816 pfd[0].events = POLLOUT;