diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/regress/lib/libssl/dtls/dtlstest.c | 161 |
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 | ||
| 53 | struct bio_packet_monkey_ctx { | 56 | struct 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 | ||
| 58 | static int | 65 | static 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 | ||
| 96 | static int | ||
| 97 | bio_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 | |||
| 88 | static long | 117 | static long |
| 89 | bio_packet_monkey_ctrl(BIO *bio, int cmd, long num, void *ptr) | 118 | bio_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 | |||
| 134 | bio_packet_monkey_write(BIO *bio, const char *in, int in_len) | 185 | bio_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 | ||
| 196 | static int | 288 | static int |
| 289 | BIO_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 | ||
| 298 | static int | ||
| 299 | BIO_packet_monkey_delay_flush(BIO *bio) | ||
| 300 | { | ||
| 301 | return BIO_ctrl(bio, BIO_C_DELAY_FLUSH, 0, NULL); | ||
| 302 | } | ||
| 303 | #endif | ||
| 304 | |||
| 305 | static int | ||
| 197 | BIO_packet_monkey_drop(BIO *bio, int num) | 306 | BIO_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 | ||
| 634 | struct dtls_delay { | ||
| 635 | uint8_t packet; | ||
| 636 | uint8_t count; | ||
| 637 | }; | ||
| 638 | |||
| 524 | struct dtls_test { | 639 | struct 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 | ||
| 628 | static void | 752 | static void |
| 629 | dtlstest_packet_monkey(SSL *ssl, const uint8_t drops[]) | 753 | dtlstest_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; |
