1 | /*
|
---|
2 | * Copyright 2016-2022 The OpenSSL Project Authors. All Rights Reserved.
|
---|
3 | *
|
---|
4 | * Licensed under the Apache License 2.0 (the "License"). You may not use
|
---|
5 | * this file except in compliance with the License. You can obtain a copy
|
---|
6 | * in the file LICENSE in the source distribution or at
|
---|
7 | * https://www.openssl.org/source/license.html
|
---|
8 | */
|
---|
9 |
|
---|
10 | #include <stdio.h>
|
---|
11 | #include <string.h>
|
---|
12 |
|
---|
13 | #include <openssl/dtls1.h>
|
---|
14 | #include <openssl/ssl.h>
|
---|
15 | #include <openssl/err.h>
|
---|
16 |
|
---|
17 | #include "helpers/ssltestlib.h"
|
---|
18 | #include "testutil.h"
|
---|
19 |
|
---|
20 | /* for SSL_READ_ETM() */
|
---|
21 | #include "../ssl/ssl_local.h"
|
---|
22 |
|
---|
23 | static int debug = 0;
|
---|
24 |
|
---|
25 | static unsigned int clnt_psk_callback(SSL *ssl, const char *hint,
|
---|
26 | char *ident, unsigned int max_ident_len,
|
---|
27 | unsigned char *psk,
|
---|
28 | unsigned int max_psk_len)
|
---|
29 | {
|
---|
30 | BIO_snprintf(ident, max_ident_len, "psk");
|
---|
31 |
|
---|
32 | if (max_psk_len > 20)
|
---|
33 | max_psk_len = 20;
|
---|
34 | memset(psk, 0x5a, max_psk_len);
|
---|
35 |
|
---|
36 | return max_psk_len;
|
---|
37 | }
|
---|
38 |
|
---|
39 | static unsigned int srvr_psk_callback(SSL *ssl, const char *identity,
|
---|
40 | unsigned char *psk,
|
---|
41 | unsigned int max_psk_len)
|
---|
42 | {
|
---|
43 | if (max_psk_len > 20)
|
---|
44 | max_psk_len = 20;
|
---|
45 | memset(psk, 0x5a, max_psk_len);
|
---|
46 | return max_psk_len;
|
---|
47 | }
|
---|
48 |
|
---|
49 | static int mtu_test(SSL_CTX *ctx, const char *cs, int no_etm)
|
---|
50 | {
|
---|
51 | SSL *srvr_ssl = NULL, *clnt_ssl = NULL;
|
---|
52 | BIO *sc_bio = NULL;
|
---|
53 | int i;
|
---|
54 | size_t s;
|
---|
55 | size_t mtus[30];
|
---|
56 | unsigned char buf[600];
|
---|
57 | int rv = 0;
|
---|
58 |
|
---|
59 | memset(buf, 0x5a, sizeof(buf));
|
---|
60 |
|
---|
61 | if (!TEST_true(create_ssl_objects(ctx, ctx, &srvr_ssl, &clnt_ssl,
|
---|
62 | NULL, NULL)))
|
---|
63 | goto end;
|
---|
64 |
|
---|
65 | if (no_etm)
|
---|
66 | SSL_set_options(srvr_ssl, SSL_OP_NO_ENCRYPT_THEN_MAC);
|
---|
67 |
|
---|
68 | if (!TEST_true(SSL_set_cipher_list(srvr_ssl, cs))
|
---|
69 | || !TEST_true(SSL_set_cipher_list(clnt_ssl, cs))
|
---|
70 | || !TEST_ptr(sc_bio = SSL_get_rbio(srvr_ssl))
|
---|
71 | || !TEST_true(create_ssl_connection(clnt_ssl, srvr_ssl,
|
---|
72 | SSL_ERROR_NONE)))
|
---|
73 | goto end;
|
---|
74 |
|
---|
75 | if (debug)
|
---|
76 | TEST_info("Channel established");
|
---|
77 |
|
---|
78 | /* For record MTU values between 500 and 539, call DTLS_get_data_mtu()
|
---|
79 | * to query the payload MTU which will fit. */
|
---|
80 | for (i = 0; i < 30; i++) {
|
---|
81 | SSL_set_mtu(clnt_ssl, 500 + i);
|
---|
82 | mtus[i] = DTLS_get_data_mtu(clnt_ssl);
|
---|
83 | if (debug)
|
---|
84 | TEST_info("%s%s MTU for record mtu %d = %lu",
|
---|
85 | cs, no_etm ? "-noEtM" : "",
|
---|
86 | 500 + i, (unsigned long)mtus[i]);
|
---|
87 | if (!TEST_size_t_ne(mtus[i], 0)) {
|
---|
88 | TEST_info("Cipher %s MTU %d", cs, 500 + i);
|
---|
89 | goto end;
|
---|
90 | }
|
---|
91 | }
|
---|
92 |
|
---|
93 | /* Now get out of the way */
|
---|
94 | SSL_set_mtu(clnt_ssl, 1000);
|
---|
95 |
|
---|
96 | /*
|
---|
97 | * Now for all values in the range of payload MTUs, send a payload of
|
---|
98 | * that size and see what actual record size we end up with.
|
---|
99 | */
|
---|
100 | for (s = mtus[0]; s <= mtus[29]; s++) {
|
---|
101 | size_t reclen;
|
---|
102 |
|
---|
103 | if (!TEST_int_eq(SSL_write(clnt_ssl, buf, s), (int)s))
|
---|
104 | goto end;
|
---|
105 | reclen = BIO_read(sc_bio, buf, sizeof(buf));
|
---|
106 | if (debug)
|
---|
107 | TEST_info("record %zu for payload %zu", reclen, s);
|
---|
108 |
|
---|
109 | for (i = 0; i < 30; i++) {
|
---|
110 | /* DTLS_get_data_mtu() with record MTU 500+i returned mtus[i] ... */
|
---|
111 |
|
---|
112 | if (!TEST_false(s <= mtus[i] && reclen > (size_t)(500 + i))) {
|
---|
113 | /*
|
---|
114 | * We sent a packet smaller than or equal to mtus[j] and
|
---|
115 | * that made a record *larger* than the record MTU 500+j!
|
---|
116 | */
|
---|
117 | TEST_error("%s: s=%lu, mtus[i]=%lu, reclen=%lu, i=%d",
|
---|
118 | cs, (unsigned long)s, (unsigned long)mtus[i],
|
---|
119 | (unsigned long)reclen, 500 + i);
|
---|
120 | goto end;
|
---|
121 | }
|
---|
122 | if (!TEST_false(s > mtus[i] && reclen <= (size_t)(500 + i))) {
|
---|
123 | /*
|
---|
124 | * We sent a *larger* packet than mtus[i] and that *still*
|
---|
125 | * fits within the record MTU 500+i, so DTLS_get_data_mtu()
|
---|
126 | * was overly pessimistic.
|
---|
127 | */
|
---|
128 | TEST_error("%s: s=%lu, mtus[i]=%lu, reclen=%lu, i=%d",
|
---|
129 | cs, (unsigned long)s, (unsigned long)mtus[i],
|
---|
130 | (unsigned long)reclen, 500 + i);
|
---|
131 | goto end;
|
---|
132 | }
|
---|
133 | }
|
---|
134 | }
|
---|
135 | rv = 1;
|
---|
136 | if (SSL_READ_ETM(clnt_ssl))
|
---|
137 | rv = 2;
|
---|
138 | end:
|
---|
139 | SSL_free(clnt_ssl);
|
---|
140 | SSL_free(srvr_ssl);
|
---|
141 | return rv;
|
---|
142 | }
|
---|
143 |
|
---|
144 | static int run_mtu_tests(void)
|
---|
145 | {
|
---|
146 | SSL_CTX *ctx = NULL;
|
---|
147 | STACK_OF(SSL_CIPHER) *ciphers;
|
---|
148 | int i, ret = 0;
|
---|
149 |
|
---|
150 | if (!TEST_ptr(ctx = SSL_CTX_new(DTLS_method())))
|
---|
151 | goto end;
|
---|
152 |
|
---|
153 | SSL_CTX_set_psk_server_callback(ctx, srvr_psk_callback);
|
---|
154 | SSL_CTX_set_psk_client_callback(ctx, clnt_psk_callback);
|
---|
155 | SSL_CTX_set_security_level(ctx, 0);
|
---|
156 |
|
---|
157 | /*
|
---|
158 | * We only care about iterating over each enc/mac; we don't want to
|
---|
159 | * repeat the test for each auth/kx variant. So keep life simple and
|
---|
160 | * only do (non-DH) PSK.
|
---|
161 | */
|
---|
162 | if (!TEST_true(SSL_CTX_set_cipher_list(ctx, "PSK")))
|
---|
163 | goto end;
|
---|
164 |
|
---|
165 | ciphers = SSL_CTX_get_ciphers(ctx);
|
---|
166 | for (i = 0; i < sk_SSL_CIPHER_num(ciphers); i++) {
|
---|
167 | const SSL_CIPHER *cipher = sk_SSL_CIPHER_value(ciphers, i);
|
---|
168 | const char *cipher_name = SSL_CIPHER_get_name(cipher);
|
---|
169 |
|
---|
170 | /* As noted above, only one test for each enc/mac variant. */
|
---|
171 | if (strncmp(cipher_name, "PSK-", 4) != 0)
|
---|
172 | continue;
|
---|
173 |
|
---|
174 | if (!TEST_int_gt(ret = mtu_test(ctx, cipher_name, 0), 0))
|
---|
175 | break;
|
---|
176 | TEST_info("%s OK", cipher_name);
|
---|
177 | if (ret == 1)
|
---|
178 | continue;
|
---|
179 |
|
---|
180 | /* mtu_test() returns 2 if it used Encrypt-then-MAC */
|
---|
181 | if (!TEST_int_gt(ret = mtu_test(ctx, cipher_name, 1), 0))
|
---|
182 | break;
|
---|
183 | TEST_info("%s without EtM OK", cipher_name);
|
---|
184 | }
|
---|
185 |
|
---|
186 | end:
|
---|
187 | SSL_CTX_free(ctx);
|
---|
188 | return ret;
|
---|
189 | }
|
---|
190 |
|
---|
191 | static int test_server_mtu_larger_than_max_fragment_length(void)
|
---|
192 | {
|
---|
193 | SSL_CTX *ctx = NULL;
|
---|
194 | SSL *srvr_ssl = NULL, *clnt_ssl = NULL;
|
---|
195 | int rv = 0;
|
---|
196 |
|
---|
197 | if (!TEST_ptr(ctx = SSL_CTX_new(DTLS_method())))
|
---|
198 | goto end;
|
---|
199 |
|
---|
200 | SSL_CTX_set_psk_server_callback(ctx, srvr_psk_callback);
|
---|
201 | SSL_CTX_set_psk_client_callback(ctx, clnt_psk_callback);
|
---|
202 |
|
---|
203 | #ifndef OPENSSL_NO_DH
|
---|
204 | if (!TEST_true(SSL_CTX_set_dh_auto(ctx, 1)))
|
---|
205 | goto end;
|
---|
206 | #endif
|
---|
207 |
|
---|
208 | if (!TEST_true(create_ssl_objects(ctx, ctx, &srvr_ssl, &clnt_ssl,
|
---|
209 | NULL, NULL)))
|
---|
210 | goto end;
|
---|
211 |
|
---|
212 | SSL_set_options(srvr_ssl, SSL_OP_NO_QUERY_MTU);
|
---|
213 | if (!TEST_true(DTLS_set_link_mtu(srvr_ssl, 1500)))
|
---|
214 | goto end;
|
---|
215 |
|
---|
216 | SSL_set_tlsext_max_fragment_length(clnt_ssl,
|
---|
217 | TLSEXT_max_fragment_length_512);
|
---|
218 |
|
---|
219 | if (!TEST_true(create_ssl_connection(srvr_ssl, clnt_ssl,
|
---|
220 | SSL_ERROR_NONE)))
|
---|
221 | goto end;
|
---|
222 |
|
---|
223 | rv = 1;
|
---|
224 |
|
---|
225 | end:
|
---|
226 | SSL_free(clnt_ssl);
|
---|
227 | SSL_free(srvr_ssl);
|
---|
228 | SSL_CTX_free(ctx);
|
---|
229 | return rv;
|
---|
230 | }
|
---|
231 |
|
---|
232 | int setup_tests(void)
|
---|
233 | {
|
---|
234 | ADD_TEST(run_mtu_tests);
|
---|
235 | ADD_TEST(test_server_mtu_larger_than_max_fragment_length);
|
---|
236 | return 1;
|
---|
237 | }
|
---|
238 |
|
---|
239 | void cleanup_tests(void)
|
---|
240 | {
|
---|
241 | bio_s_mempacket_test_free();
|
---|
242 | }
|
---|