1 | /*
|
---|
2 | * Copyright 2022-2023 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 <string.h>
|
---|
11 | #include <openssl/bio.h>
|
---|
12 | #include <openssl/rand.h>
|
---|
13 | #include "testutil.h"
|
---|
14 | #include "internal/sockets.h"
|
---|
15 | #include "internal/bio_addr.h"
|
---|
16 |
|
---|
17 | #if !defined(OPENSSL_NO_DGRAM) && !defined(OPENSSL_NO_SOCK)
|
---|
18 |
|
---|
19 | static int compare_addr(const BIO_ADDR *a, const BIO_ADDR *b)
|
---|
20 | {
|
---|
21 | struct in_addr xa, xb;
|
---|
22 | #if OPENSSL_USE_IPV6
|
---|
23 | struct in6_addr xa6, xb6;
|
---|
24 | #endif
|
---|
25 | void *pa, *pb;
|
---|
26 | size_t slen, tmplen;
|
---|
27 |
|
---|
28 | if (BIO_ADDR_family(a) != BIO_ADDR_family(b))
|
---|
29 | return 0;
|
---|
30 |
|
---|
31 | if (BIO_ADDR_family(a) == AF_INET) {
|
---|
32 | pa = &xa;
|
---|
33 | pb = &xb;
|
---|
34 | slen = sizeof(xa);
|
---|
35 | }
|
---|
36 | #if OPENSSL_USE_IPV6
|
---|
37 | else if (BIO_ADDR_family(a) == AF_INET6) {
|
---|
38 | pa = &xa6;
|
---|
39 | pb = &xb6;
|
---|
40 | slen = sizeof(xa6);
|
---|
41 | }
|
---|
42 | #endif
|
---|
43 | else {
|
---|
44 | return 0;
|
---|
45 | }
|
---|
46 |
|
---|
47 | tmplen = slen;
|
---|
48 | if (!TEST_int_eq(BIO_ADDR_rawaddress(a, pa, &tmplen), 1))
|
---|
49 | return 0;
|
---|
50 |
|
---|
51 | tmplen = slen;
|
---|
52 | if (!TEST_int_eq(BIO_ADDR_rawaddress(b, pb, &tmplen), 1))
|
---|
53 | return 0;
|
---|
54 |
|
---|
55 | if (!TEST_mem_eq(pa, slen, pb, slen))
|
---|
56 | return 0;
|
---|
57 |
|
---|
58 | if (!TEST_int_eq(BIO_ADDR_rawport(a), BIO_ADDR_rawport(b)))
|
---|
59 | return 0;
|
---|
60 |
|
---|
61 | return 1;
|
---|
62 | }
|
---|
63 |
|
---|
64 | static int do_sendmmsg(BIO *b, BIO_MSG *msg,
|
---|
65 | size_t num_msg, uint64_t flags,
|
---|
66 | size_t *num_processed)
|
---|
67 | {
|
---|
68 | size_t done;
|
---|
69 |
|
---|
70 | for (done = 0; done < num_msg; ) {
|
---|
71 | if (!BIO_sendmmsg(b, msg + done, sizeof(BIO_MSG),
|
---|
72 | num_msg - done, flags, num_processed))
|
---|
73 | return 0;
|
---|
74 |
|
---|
75 | done += *num_processed;
|
---|
76 | }
|
---|
77 |
|
---|
78 | *num_processed = done;
|
---|
79 | return 1;
|
---|
80 | }
|
---|
81 |
|
---|
82 | static int do_recvmmsg(BIO *b, BIO_MSG *msg,
|
---|
83 | size_t num_msg, uint64_t flags,
|
---|
84 | size_t *num_processed)
|
---|
85 | {
|
---|
86 | size_t done;
|
---|
87 |
|
---|
88 | for (done = 0; done < num_msg; ) {
|
---|
89 | if (!BIO_recvmmsg(b, msg + done, sizeof(BIO_MSG),
|
---|
90 | num_msg - done, flags, num_processed))
|
---|
91 | return 0;
|
---|
92 |
|
---|
93 | done += *num_processed;
|
---|
94 | }
|
---|
95 |
|
---|
96 | *num_processed = done;
|
---|
97 | return 1;
|
---|
98 | }
|
---|
99 |
|
---|
100 | static int test_bio_dgram_impl(int af, int use_local)
|
---|
101 | {
|
---|
102 | int testresult = 0;
|
---|
103 | BIO *b1 = NULL, *b2 = NULL;
|
---|
104 | int fd1 = -1, fd2 = -1;
|
---|
105 | BIO_ADDR *addr1 = NULL, *addr2 = NULL, *addr3 = NULL, *addr4 = NULL,
|
---|
106 | *addr5 = NULL, *addr6 = NULL;
|
---|
107 | struct in_addr ina;
|
---|
108 | #if OPENSSL_USE_IPV6
|
---|
109 | struct in6_addr ina6;
|
---|
110 | #endif
|
---|
111 | void *pina;
|
---|
112 | size_t inal, i;
|
---|
113 | union BIO_sock_info_u info1 = {0}, info2 = {0};
|
---|
114 | char rx_buf[128], rx_buf2[128];
|
---|
115 | BIO_MSG tx_msg[128], rx_msg[128];
|
---|
116 | char tx_buf[128];
|
---|
117 | size_t num_processed = 0;
|
---|
118 |
|
---|
119 | if (af == AF_INET) {
|
---|
120 | TEST_info("# Testing with AF_INET, local=%d\n", use_local);
|
---|
121 | pina = &ina;
|
---|
122 | inal = sizeof(ina);
|
---|
123 | }
|
---|
124 | #if OPENSSL_USE_IPV6
|
---|
125 | else if (af == AF_INET6) {
|
---|
126 | TEST_info("# Testing with AF_INET6, local=%d\n", use_local);
|
---|
127 | pina = &ina6;
|
---|
128 | inal = sizeof(ina6);
|
---|
129 | }
|
---|
130 | #endif
|
---|
131 | else {
|
---|
132 | goto err;
|
---|
133 | }
|
---|
134 |
|
---|
135 | memset(pina, 0, inal);
|
---|
136 | ina.s_addr = htonl(0x7f000001UL);
|
---|
137 | #if OPENSSL_USE_IPV6
|
---|
138 | ina6.s6_addr[15] = 1;
|
---|
139 | #endif
|
---|
140 |
|
---|
141 | addr1 = BIO_ADDR_new();
|
---|
142 | if (!TEST_ptr(addr1))
|
---|
143 | goto err;
|
---|
144 |
|
---|
145 | addr2 = BIO_ADDR_new();
|
---|
146 | if (!TEST_ptr(addr2))
|
---|
147 | goto err;
|
---|
148 |
|
---|
149 | addr3 = BIO_ADDR_new();
|
---|
150 | if (!TEST_ptr(addr3))
|
---|
151 | goto err;
|
---|
152 |
|
---|
153 | addr4 = BIO_ADDR_new();
|
---|
154 | if (!TEST_ptr(addr4))
|
---|
155 | goto err;
|
---|
156 |
|
---|
157 | addr5 = BIO_ADDR_new();
|
---|
158 | if (!TEST_ptr(addr5))
|
---|
159 | goto err;
|
---|
160 |
|
---|
161 | addr6 = BIO_ADDR_new();
|
---|
162 | if (!TEST_ptr(addr6))
|
---|
163 | goto err;
|
---|
164 |
|
---|
165 | if (!TEST_int_eq(BIO_ADDR_rawmake(addr1, af, pina, inal, 0), 1))
|
---|
166 | goto err;
|
---|
167 |
|
---|
168 | if (!TEST_int_eq(BIO_ADDR_rawmake(addr2, af, pina, inal, 0), 1))
|
---|
169 | goto err;
|
---|
170 |
|
---|
171 | fd1 = BIO_socket(af, SOCK_DGRAM, IPPROTO_UDP, 0);
|
---|
172 | if (!TEST_int_ge(fd1, 0))
|
---|
173 | goto err;
|
---|
174 |
|
---|
175 | fd2 = BIO_socket(af, SOCK_DGRAM, IPPROTO_UDP, 0);
|
---|
176 | if (!TEST_int_ge(fd2, 0))
|
---|
177 | goto err;
|
---|
178 |
|
---|
179 | if (BIO_bind(fd1, addr1, 0) <= 0
|
---|
180 | || BIO_bind(fd2, addr2, 0) <= 0) {
|
---|
181 | testresult = TEST_skip("BIO_bind() failed - assuming it's an unavailable address family");
|
---|
182 | goto err;
|
---|
183 | }
|
---|
184 |
|
---|
185 | info1.addr = addr1;
|
---|
186 | if (!TEST_int_gt(BIO_sock_info(fd1, BIO_SOCK_INFO_ADDRESS, &info1), 0))
|
---|
187 | goto err;
|
---|
188 |
|
---|
189 | info2.addr = addr2;
|
---|
190 | if (!TEST_int_gt(BIO_sock_info(fd2, BIO_SOCK_INFO_ADDRESS, &info2), 0))
|
---|
191 | goto err;
|
---|
192 |
|
---|
193 | if (!TEST_int_gt(BIO_ADDR_rawport(addr1), 0))
|
---|
194 | goto err;
|
---|
195 |
|
---|
196 | if (!TEST_int_gt(BIO_ADDR_rawport(addr2), 0))
|
---|
197 | goto err;
|
---|
198 |
|
---|
199 | b1 = BIO_new_dgram(fd1, 0);
|
---|
200 | if (!TEST_ptr(b1))
|
---|
201 | goto err;
|
---|
202 |
|
---|
203 | b2 = BIO_new_dgram(fd2, 0);
|
---|
204 | if (!TEST_ptr(b2))
|
---|
205 | goto err;
|
---|
206 |
|
---|
207 | if (!TEST_int_gt(BIO_dgram_set_peer(b1, addr2), 0))
|
---|
208 | goto err;
|
---|
209 |
|
---|
210 | if (!TEST_int_gt(BIO_write(b1, "hello", 5), 0))
|
---|
211 | goto err;
|
---|
212 |
|
---|
213 | /* Receiving automatically sets peer as source addr */
|
---|
214 | if (!TEST_int_eq(BIO_read(b2, rx_buf, sizeof(rx_buf)), 5))
|
---|
215 | goto err;
|
---|
216 |
|
---|
217 | if (!TEST_mem_eq(rx_buf, 5, "hello", 5))
|
---|
218 | goto err;
|
---|
219 |
|
---|
220 | if (!TEST_int_gt(BIO_dgram_get_peer(b2, addr3), 0))
|
---|
221 | goto err;
|
---|
222 |
|
---|
223 | if (!TEST_int_eq(compare_addr(addr3, addr1), 1))
|
---|
224 | goto err;
|
---|
225 |
|
---|
226 | /* Clear peer */
|
---|
227 | if (!TEST_int_gt(BIO_ADDR_rawmake(addr3, af, pina, inal, 0), 0))
|
---|
228 | goto err;
|
---|
229 |
|
---|
230 | if (!TEST_int_gt(BIO_dgram_set_peer(b1, addr3), 0))
|
---|
231 | goto err;
|
---|
232 |
|
---|
233 | if (!TEST_int_gt(BIO_dgram_set_peer(b2, addr3), 0))
|
---|
234 | goto err;
|
---|
235 |
|
---|
236 | /* Now test using sendmmsg/recvmmsg with no peer set */
|
---|
237 | tx_msg[0].data = "apple";
|
---|
238 | tx_msg[0].data_len = 5;
|
---|
239 | tx_msg[0].peer = NULL;
|
---|
240 | tx_msg[0].local = NULL;
|
---|
241 | tx_msg[0].flags = 0;
|
---|
242 |
|
---|
243 | tx_msg[1].data = "orange";
|
---|
244 | tx_msg[1].data_len = 6;
|
---|
245 | tx_msg[1].peer = NULL;
|
---|
246 | tx_msg[1].local = NULL;
|
---|
247 | tx_msg[1].flags = 0;
|
---|
248 |
|
---|
249 | /* First effort should fail due to missing destination address */
|
---|
250 | if (!TEST_false(do_sendmmsg(b1, tx_msg, 2, 0, &num_processed))
|
---|
251 | || !TEST_size_t_eq(num_processed, 0))
|
---|
252 | goto err;
|
---|
253 |
|
---|
254 | /*
|
---|
255 | * Second effort should fail due to local being requested
|
---|
256 | * when not enabled
|
---|
257 | */
|
---|
258 | tx_msg[0].peer = addr2;
|
---|
259 | tx_msg[0].local = addr1;
|
---|
260 | tx_msg[1].peer = addr2;
|
---|
261 | tx_msg[1].local = addr1;
|
---|
262 | if (!TEST_false(do_sendmmsg(b1, tx_msg, 2, 0, &num_processed)
|
---|
263 | || !TEST_size_t_eq(num_processed, 0)))
|
---|
264 | goto err;
|
---|
265 |
|
---|
266 | /* Enable local if we are using it */
|
---|
267 | if (BIO_dgram_get_local_addr_cap(b1) > 0 && use_local) {
|
---|
268 | if (!TEST_int_eq(BIO_dgram_set_local_addr_enable(b1, 1), 1))
|
---|
269 | goto err;
|
---|
270 | } else {
|
---|
271 | tx_msg[0].local = NULL;
|
---|
272 | tx_msg[1].local = NULL;
|
---|
273 | use_local = 0;
|
---|
274 | }
|
---|
275 |
|
---|
276 | /* Third effort should succeed */
|
---|
277 | if (!TEST_true(do_sendmmsg(b1, tx_msg, 2, 0, &num_processed))
|
---|
278 | || !TEST_size_t_eq(num_processed, 2))
|
---|
279 | goto err;
|
---|
280 |
|
---|
281 | /* Now try receiving */
|
---|
282 | rx_msg[0].data = rx_buf;
|
---|
283 | rx_msg[0].data_len = sizeof(rx_buf);
|
---|
284 | rx_msg[0].peer = addr3;
|
---|
285 | rx_msg[0].local = addr4;
|
---|
286 | rx_msg[0].flags = (1UL<<31); /* undefined flag, should be erased */
|
---|
287 | memset(rx_buf, 0, sizeof(rx_buf));
|
---|
288 |
|
---|
289 | rx_msg[1].data = rx_buf2;
|
---|
290 | rx_msg[1].data_len = sizeof(rx_buf2);
|
---|
291 | rx_msg[1].peer = addr5;
|
---|
292 | rx_msg[1].local = addr6;
|
---|
293 | rx_msg[1].flags = (1UL<<31); /* undefined flag, should be erased */
|
---|
294 | memset(rx_buf2, 0, sizeof(rx_buf2));
|
---|
295 |
|
---|
296 | /*
|
---|
297 | * Should fail at first due to local being requested when not
|
---|
298 | * enabled
|
---|
299 | */
|
---|
300 | if (!TEST_false(do_recvmmsg(b2, rx_msg, 2, 0, &num_processed))
|
---|
301 | || !TEST_size_t_eq(num_processed, 0))
|
---|
302 | goto err;
|
---|
303 |
|
---|
304 | /* Fields have not been modified */
|
---|
305 | if (!TEST_int_eq((int)rx_msg[0].data_len, sizeof(rx_buf)))
|
---|
306 | goto err;
|
---|
307 |
|
---|
308 | if (!TEST_int_eq((int)rx_msg[1].data_len, sizeof(rx_buf2)))
|
---|
309 | goto err;
|
---|
310 |
|
---|
311 | if (!TEST_ulong_eq((unsigned long)rx_msg[0].flags, 1UL<<31))
|
---|
312 | goto err;
|
---|
313 |
|
---|
314 | if (!TEST_ulong_eq((unsigned long)rx_msg[1].flags, 1UL<<31))
|
---|
315 | goto err;
|
---|
316 |
|
---|
317 | /* Enable local if we are using it */
|
---|
318 | if (BIO_dgram_get_local_addr_cap(b2) > 0 && use_local) {
|
---|
319 | if (!TEST_int_eq(BIO_dgram_set_local_addr_enable(b2, 1), 1))
|
---|
320 | goto err;
|
---|
321 | } else {
|
---|
322 | rx_msg[0].local = NULL;
|
---|
323 | rx_msg[1].local = NULL;
|
---|
324 | use_local = 0;
|
---|
325 | }
|
---|
326 |
|
---|
327 | /* Do the receive. */
|
---|
328 | if (!TEST_true(do_recvmmsg(b2, rx_msg, 2, 0, &num_processed))
|
---|
329 | || !TEST_size_t_eq(num_processed, 2))
|
---|
330 | goto err;
|
---|
331 |
|
---|
332 | /* data_len should have been updated correctly */
|
---|
333 | if (!TEST_int_eq((int)rx_msg[0].data_len, 5))
|
---|
334 | goto err;
|
---|
335 |
|
---|
336 | if (!TEST_int_eq((int)rx_msg[1].data_len, 6))
|
---|
337 | goto err;
|
---|
338 |
|
---|
339 | /* flags should have been zeroed */
|
---|
340 | if (!TEST_int_eq((int)rx_msg[0].flags, 0))
|
---|
341 | goto err;
|
---|
342 |
|
---|
343 | if (!TEST_int_eq((int)rx_msg[1].flags, 0))
|
---|
344 | goto err;
|
---|
345 |
|
---|
346 | /* peer address should match expected */
|
---|
347 | if (!TEST_int_eq(compare_addr(addr3, addr1), 1))
|
---|
348 | goto err;
|
---|
349 |
|
---|
350 | if (!TEST_int_eq(compare_addr(addr5, addr1), 1))
|
---|
351 | goto err;
|
---|
352 |
|
---|
353 | /*
|
---|
354 | * Do not test local address yet as some platforms do not reliably return
|
---|
355 | * local addresses for messages queued for RX before local address support
|
---|
356 | * was enabled. Instead, send some new messages and test they're received
|
---|
357 | * with the correct local addresses.
|
---|
358 | */
|
---|
359 | if (!TEST_true(do_sendmmsg(b1, tx_msg, 2, 0, &num_processed))
|
---|
360 | || !TEST_size_t_eq(num_processed, 2))
|
---|
361 | goto err;
|
---|
362 |
|
---|
363 | /* Receive the messages. */
|
---|
364 | rx_msg[0].data_len = sizeof(rx_buf);
|
---|
365 | rx_msg[1].data_len = sizeof(rx_buf2);
|
---|
366 |
|
---|
367 | if (!TEST_true(do_recvmmsg(b2, rx_msg, 2, 0, &num_processed))
|
---|
368 | || !TEST_size_t_eq(num_processed, 2))
|
---|
369 | goto err;
|
---|
370 |
|
---|
371 | if (rx_msg[0].local != NULL) {
|
---|
372 | /* If we are using local, it should match expected */
|
---|
373 | if (!TEST_int_eq(compare_addr(addr4, addr2), 1))
|
---|
374 | goto err;
|
---|
375 |
|
---|
376 | if (!TEST_int_eq(compare_addr(addr6, addr2), 1))
|
---|
377 | goto err;
|
---|
378 | }
|
---|
379 |
|
---|
380 | /*
|
---|
381 | * Try sending more than can be handled in one sendmmsg call (when using the
|
---|
382 | * sendmmsg implementation)
|
---|
383 | */
|
---|
384 | for (i = 0; i < OSSL_NELEM(tx_msg); ++i) {
|
---|
385 | tx_buf[i] = (char)i;
|
---|
386 | tx_msg[i].data = tx_buf + i;
|
---|
387 | tx_msg[i].data_len = 1;
|
---|
388 | tx_msg[i].peer = addr2;
|
---|
389 | tx_msg[i].local = use_local ? addr1 : NULL;
|
---|
390 | tx_msg[i].flags = 0;
|
---|
391 | }
|
---|
392 | if (!TEST_true(do_sendmmsg(b1, tx_msg, OSSL_NELEM(tx_msg), 0, &num_processed))
|
---|
393 | || !TEST_size_t_eq(num_processed, OSSL_NELEM(tx_msg)))
|
---|
394 | goto err;
|
---|
395 |
|
---|
396 | /*
|
---|
397 | * Try receiving more than can be handled in one recvmmsg call (when using
|
---|
398 | * the recvmmsg implementation)
|
---|
399 | */
|
---|
400 | for (i = 0; i < OSSL_NELEM(rx_msg); ++i) {
|
---|
401 | rx_buf[i] = '\0';
|
---|
402 | rx_msg[i].data = rx_buf + i;
|
---|
403 | rx_msg[i].data_len = 1;
|
---|
404 | rx_msg[i].peer = NULL;
|
---|
405 | rx_msg[i].local = NULL;
|
---|
406 | rx_msg[i].flags = 0;
|
---|
407 | }
|
---|
408 | if (!TEST_true(do_recvmmsg(b2, rx_msg, OSSL_NELEM(rx_msg), 0, &num_processed))
|
---|
409 | || !TEST_size_t_eq(num_processed, OSSL_NELEM(rx_msg)))
|
---|
410 | goto err;
|
---|
411 |
|
---|
412 | if (!TEST_mem_eq(tx_buf, OSSL_NELEM(tx_msg), rx_buf, OSSL_NELEM(tx_msg)))
|
---|
413 | goto err;
|
---|
414 |
|
---|
415 | testresult = 1;
|
---|
416 | err:
|
---|
417 | BIO_free(b1);
|
---|
418 | BIO_free(b2);
|
---|
419 | if (fd1 >= 0)
|
---|
420 | BIO_closesocket(fd1);
|
---|
421 | if (fd2 >= 0)
|
---|
422 | BIO_closesocket(fd2);
|
---|
423 | BIO_ADDR_free(addr1);
|
---|
424 | BIO_ADDR_free(addr2);
|
---|
425 | BIO_ADDR_free(addr3);
|
---|
426 | BIO_ADDR_free(addr4);
|
---|
427 | BIO_ADDR_free(addr5);
|
---|
428 | BIO_ADDR_free(addr6);
|
---|
429 | return testresult;
|
---|
430 | }
|
---|
431 |
|
---|
432 | struct bio_dgram_case {
|
---|
433 | int af, local;
|
---|
434 | };
|
---|
435 |
|
---|
436 | static const struct bio_dgram_case bio_dgram_cases[] = {
|
---|
437 | /* Test without local */
|
---|
438 | { AF_INET, 0 },
|
---|
439 | #if OPENSSL_USE_IPV6
|
---|
440 | { AF_INET6, 0 },
|
---|
441 | #endif
|
---|
442 | /* Test with local */
|
---|
443 | { AF_INET, 1 },
|
---|
444 | #if OPENSSL_USE_IPV6
|
---|
445 | { AF_INET6, 1 }
|
---|
446 | #endif
|
---|
447 | };
|
---|
448 |
|
---|
449 | static int test_bio_dgram(int idx)
|
---|
450 | {
|
---|
451 | return test_bio_dgram_impl(bio_dgram_cases[idx].af,
|
---|
452 | bio_dgram_cases[idx].local);
|
---|
453 | }
|
---|
454 |
|
---|
455 | # if !defined(OPENSSL_NO_CHACHA)
|
---|
456 | static int random_data(const uint32_t *key, uint8_t *data, size_t data_len, size_t offset)
|
---|
457 | {
|
---|
458 | int ret = 0, outl;
|
---|
459 | EVP_CIPHER_CTX *ctx = NULL;
|
---|
460 | EVP_CIPHER *cipher = NULL;
|
---|
461 | static const uint8_t zeroes[2048];
|
---|
462 | uint32_t counter[4] = {0};
|
---|
463 |
|
---|
464 | counter[0] = (uint32_t)offset;
|
---|
465 |
|
---|
466 | ctx = EVP_CIPHER_CTX_new();
|
---|
467 | if (ctx == NULL)
|
---|
468 | goto err;
|
---|
469 |
|
---|
470 | cipher = EVP_CIPHER_fetch(NULL, "ChaCha20", NULL);
|
---|
471 | if (cipher == NULL)
|
---|
472 | goto err;
|
---|
473 |
|
---|
474 | if (EVP_EncryptInit_ex2(ctx, cipher, (uint8_t *)key, (uint8_t *)counter, NULL) == 0)
|
---|
475 | goto err;
|
---|
476 |
|
---|
477 | while (data_len > 0) {
|
---|
478 | outl = data_len > sizeof(zeroes) ? (int)sizeof(zeroes) : (int)data_len;
|
---|
479 | if (EVP_EncryptUpdate(ctx, data, &outl, zeroes, outl) != 1)
|
---|
480 | goto err;
|
---|
481 |
|
---|
482 | data += outl;
|
---|
483 | data_len -= outl;
|
---|
484 | }
|
---|
485 |
|
---|
486 | ret = 1;
|
---|
487 | err:
|
---|
488 | EVP_CIPHER_CTX_free(ctx);
|
---|
489 | EVP_CIPHER_free(cipher);
|
---|
490 | return ret;
|
---|
491 | }
|
---|
492 |
|
---|
493 | static int test_bio_dgram_pair(int idx)
|
---|
494 | {
|
---|
495 | int testresult = 0, blen, mtu1, mtu2, r;
|
---|
496 | BIO *bio1 = NULL, *bio2 = NULL;
|
---|
497 | uint8_t scratch[2048 + 4], scratch2[2048];
|
---|
498 | uint32_t key[8];
|
---|
499 | size_t i, num_dgram, num_processed = 0;
|
---|
500 | BIO_MSG msgs[2], rmsgs[2];
|
---|
501 | BIO_ADDR *addr1 = NULL, *addr2 = NULL, *addr3 = NULL, *addr4 = NULL;
|
---|
502 | struct in_addr in_local;
|
---|
503 | size_t total = 0;
|
---|
504 | const uint32_t ref_caps = BIO_DGRAM_CAP_HANDLES_SRC_ADDR
|
---|
505 | | BIO_DGRAM_CAP_HANDLES_DST_ADDR
|
---|
506 | | BIO_DGRAM_CAP_PROVIDES_SRC_ADDR
|
---|
507 | | BIO_DGRAM_CAP_PROVIDES_DST_ADDR;
|
---|
508 |
|
---|
509 | memset(msgs, 0, sizeof(msgs));
|
---|
510 | memset(rmsgs, 0, sizeof(rmsgs));
|
---|
511 |
|
---|
512 | in_local.s_addr = ntohl(0x7f000001);
|
---|
513 |
|
---|
514 | for (i = 0; i < OSSL_NELEM(key); ++i)
|
---|
515 | key[i] = test_random();
|
---|
516 |
|
---|
517 | if (idx == 0) {
|
---|
518 | if (!TEST_int_eq(BIO_new_bio_dgram_pair(&bio1, 0, &bio2, 0), 1))
|
---|
519 | goto err;
|
---|
520 | } else {
|
---|
521 | if (!TEST_ptr(bio1 = bio2 = BIO_new(BIO_s_dgram_mem())))
|
---|
522 | goto err;
|
---|
523 | }
|
---|
524 |
|
---|
525 | mtu1 = BIO_dgram_get_mtu(bio1);
|
---|
526 | if (!TEST_int_ge(mtu1, 1280))
|
---|
527 | goto err;
|
---|
528 |
|
---|
529 | if (idx == 1) {
|
---|
530 | size_t bufsz;
|
---|
531 |
|
---|
532 | /*
|
---|
533 | * Assume the header contains 2 BIO_ADDR structures and a length. We
|
---|
534 | * set a buffer big enough for 9 full sized datagrams.
|
---|
535 | */
|
---|
536 | bufsz = 9 * (mtu1 + (sizeof(BIO_ADDR) * 2) + sizeof(size_t));
|
---|
537 | if (!TEST_true(BIO_set_write_buf_size(bio1, bufsz)))
|
---|
538 | goto err;
|
---|
539 | }
|
---|
540 |
|
---|
541 | mtu2 = BIO_dgram_get_mtu(bio2);
|
---|
542 | if (!TEST_int_ge(mtu2, 1280))
|
---|
543 | goto err;
|
---|
544 |
|
---|
545 | if (!TEST_int_eq(mtu1, mtu2))
|
---|
546 | goto err;
|
---|
547 |
|
---|
548 | if (!TEST_int_le(mtu1, sizeof(scratch) - 4))
|
---|
549 | goto err;
|
---|
550 |
|
---|
551 | for (i = 0; total < 1 * 1024 * 1024; ++i) {
|
---|
552 | if (!TEST_int_eq(random_data(key, scratch, sizeof(scratch), i), 1))
|
---|
553 | goto err;
|
---|
554 |
|
---|
555 | blen = ((*(uint32_t*)scratch) % mtu1) + 1;
|
---|
556 | r = BIO_write(bio1, scratch + 4, blen);
|
---|
557 | if (r == -1)
|
---|
558 | break;
|
---|
559 |
|
---|
560 | if (!TEST_int_eq(r, blen))
|
---|
561 | goto err;
|
---|
562 |
|
---|
563 | total += blen;
|
---|
564 | }
|
---|
565 |
|
---|
566 | if (idx <= 1 && !TEST_size_t_lt(total, 1 * 1024 * 1024))
|
---|
567 | goto err;
|
---|
568 |
|
---|
569 | if (idx == 2 && !TEST_size_t_ge(total, 1 * 1024 * 1024))
|
---|
570 | goto err;
|
---|
571 |
|
---|
572 | /*
|
---|
573 | * The number of datagrams we can fit depends on the size of the default
|
---|
574 | * write buffer size, the size of the datagram header and the size of the
|
---|
575 | * payload data we send in each datagram. The max payload data is based on
|
---|
576 | * the mtu. The default write buffer size is 9 * (sizeof(header) + mtu) so
|
---|
577 | * we expect at least 9 maximally sized datagrams to fit in the buffer.
|
---|
578 | */
|
---|
579 | if (!TEST_int_ge(i, 9))
|
---|
580 | goto err;
|
---|
581 |
|
---|
582 | /* Check we read back the same data */
|
---|
583 | num_dgram = i;
|
---|
584 | for (i = 0; i < num_dgram; ++i) {
|
---|
585 | if (!TEST_int_eq(random_data(key, scratch, sizeof(scratch), i), 1))
|
---|
586 | goto err;
|
---|
587 |
|
---|
588 | blen = ((*(uint32_t*)scratch) % mtu1) + 1;
|
---|
589 | r = BIO_read(bio2, scratch2, sizeof(scratch2));
|
---|
590 | if (!TEST_int_eq(r, blen))
|
---|
591 | goto err;
|
---|
592 |
|
---|
593 | if (!TEST_mem_eq(scratch + 4, blen, scratch2, blen))
|
---|
594 | goto err;
|
---|
595 | }
|
---|
596 |
|
---|
597 | /* Should now be out of data */
|
---|
598 | if (!TEST_int_eq(BIO_read(bio2, scratch2, sizeof(scratch2)), -1))
|
---|
599 | goto err;
|
---|
600 |
|
---|
601 | /* sendmmsg/recvmmsg */
|
---|
602 | if (!TEST_int_eq(random_data(key, scratch, sizeof(scratch), 0), 1))
|
---|
603 | goto err;
|
---|
604 |
|
---|
605 | msgs[0].data = scratch;
|
---|
606 | msgs[0].data_len = 19;
|
---|
607 | msgs[1].data = scratch + 19;
|
---|
608 | msgs[1].data_len = 46;
|
---|
609 |
|
---|
610 | if (!TEST_true(BIO_sendmmsg(bio1, msgs, sizeof(BIO_MSG), OSSL_NELEM(msgs), 0,
|
---|
611 | &num_processed))
|
---|
612 | || !TEST_size_t_eq(num_processed, 2))
|
---|
613 | goto err;
|
---|
614 |
|
---|
615 | rmsgs[0].data = scratch2;
|
---|
616 | rmsgs[0].data_len = 64;
|
---|
617 | rmsgs[1].data = scratch2 + 64;
|
---|
618 | rmsgs[1].data_len = 64;
|
---|
619 | if (!TEST_true(BIO_recvmmsg(bio2, rmsgs, sizeof(BIO_MSG), OSSL_NELEM(rmsgs), 0,
|
---|
620 | &num_processed))
|
---|
621 | || !TEST_size_t_eq(num_processed, 2))
|
---|
622 | goto err;
|
---|
623 |
|
---|
624 | if (!TEST_mem_eq(rmsgs[0].data, rmsgs[0].data_len, scratch, 19))
|
---|
625 | goto err;
|
---|
626 |
|
---|
627 | if (!TEST_mem_eq(rmsgs[1].data, rmsgs[1].data_len, scratch + 19, 46))
|
---|
628 | goto err;
|
---|
629 |
|
---|
630 | /* sendmmsg/recvmmsg with peer */
|
---|
631 | addr1 = BIO_ADDR_new();
|
---|
632 | if (!TEST_ptr(addr1))
|
---|
633 | goto err;
|
---|
634 |
|
---|
635 | if (!TEST_int_eq(BIO_ADDR_rawmake(addr1, AF_INET, &in_local,
|
---|
636 | sizeof(in_local), 1234), 1))
|
---|
637 | goto err;
|
---|
638 |
|
---|
639 | addr2 = BIO_ADDR_new();
|
---|
640 | if (!TEST_ptr(addr2))
|
---|
641 | goto err;
|
---|
642 |
|
---|
643 | if (!TEST_int_eq(BIO_ADDR_rawmake(addr2, AF_INET, &in_local,
|
---|
644 | sizeof(in_local), 2345), 1))
|
---|
645 | goto err;
|
---|
646 |
|
---|
647 | addr3 = BIO_ADDR_new();
|
---|
648 | if (!TEST_ptr(addr3))
|
---|
649 | goto err;
|
---|
650 |
|
---|
651 | addr4 = BIO_ADDR_new();
|
---|
652 | if (!TEST_ptr(addr4))
|
---|
653 | goto err;
|
---|
654 |
|
---|
655 | msgs[0].peer = addr1;
|
---|
656 |
|
---|
657 | /* fails due to lack of caps on peer */
|
---|
658 | if (!TEST_false(BIO_sendmmsg(bio1, msgs, sizeof(BIO_MSG),
|
---|
659 | OSSL_NELEM(msgs), 0, &num_processed))
|
---|
660 | || !TEST_size_t_eq(num_processed, 0))
|
---|
661 | goto err;
|
---|
662 |
|
---|
663 | if (!TEST_int_eq(BIO_dgram_set_caps(bio2, ref_caps), 1))
|
---|
664 | goto err;
|
---|
665 |
|
---|
666 | if (!TEST_int_eq(BIO_dgram_get_caps(bio2), ref_caps))
|
---|
667 | goto err;
|
---|
668 |
|
---|
669 | if (!TEST_int_eq(BIO_dgram_get_effective_caps(bio1), ref_caps))
|
---|
670 | goto err;
|
---|
671 |
|
---|
672 | if (idx == 0 && !TEST_int_eq(BIO_dgram_get_effective_caps(bio2), 0))
|
---|
673 | goto err;
|
---|
674 |
|
---|
675 | if (!TEST_int_eq(BIO_dgram_set_caps(bio1, ref_caps), 1))
|
---|
676 | goto err;
|
---|
677 |
|
---|
678 | /* succeeds with cap now available */
|
---|
679 | if (!TEST_true(BIO_sendmmsg(bio1, msgs, sizeof(BIO_MSG), 1, 0, &num_processed))
|
---|
680 | || !TEST_size_t_eq(num_processed, 1))
|
---|
681 | goto err;
|
---|
682 |
|
---|
683 | /* enable local addr support */
|
---|
684 | if (!TEST_int_eq(BIO_dgram_set_local_addr_enable(bio2, 1), 1))
|
---|
685 | goto err;
|
---|
686 |
|
---|
687 | rmsgs[0].data = scratch2;
|
---|
688 | rmsgs[0].data_len = 64;
|
---|
689 | rmsgs[0].peer = addr3;
|
---|
690 | rmsgs[0].local = addr4;
|
---|
691 | if (!TEST_true(BIO_recvmmsg(bio2, rmsgs, sizeof(BIO_MSG), OSSL_NELEM(rmsgs), 0,
|
---|
692 | &num_processed))
|
---|
693 | || !TEST_size_t_eq(num_processed, 1))
|
---|
694 | goto err;
|
---|
695 |
|
---|
696 | if (!TEST_mem_eq(rmsgs[0].data, rmsgs[0].data_len, msgs[0].data, 19))
|
---|
697 | goto err;
|
---|
698 |
|
---|
699 | /* We didn't set the source address so this should be zero */
|
---|
700 | if (!TEST_int_eq(BIO_ADDR_family(addr3), 0))
|
---|
701 | goto err;
|
---|
702 |
|
---|
703 | if (!TEST_int_eq(BIO_ADDR_family(addr4), AF_INET))
|
---|
704 | goto err;
|
---|
705 |
|
---|
706 | if (!TEST_int_eq(BIO_ADDR_rawport(addr4), 1234))
|
---|
707 | goto err;
|
---|
708 |
|
---|
709 | /* test source address */
|
---|
710 | msgs[0].local = addr2;
|
---|
711 |
|
---|
712 | if (!TEST_int_eq(BIO_dgram_set_local_addr_enable(bio1, 1), 1))
|
---|
713 | goto err;
|
---|
714 |
|
---|
715 | if (!TEST_true(BIO_sendmmsg(bio1, msgs, sizeof(BIO_MSG), 1, 0, &num_processed))
|
---|
716 | || !TEST_size_t_eq(num_processed, 1))
|
---|
717 | goto err;
|
---|
718 |
|
---|
719 | rmsgs[0].data = scratch2;
|
---|
720 | rmsgs[0].data_len = 64;
|
---|
721 | if (!TEST_true(BIO_recvmmsg(bio2, rmsgs, sizeof(BIO_MSG), OSSL_NELEM(rmsgs), 0, &num_processed))
|
---|
722 | || !TEST_size_t_eq(num_processed, 1))
|
---|
723 | goto err;
|
---|
724 |
|
---|
725 | if (!TEST_mem_eq(rmsgs[0].data, rmsgs[0].data_len,
|
---|
726 | msgs[0].data, msgs[0].data_len))
|
---|
727 | goto err;
|
---|
728 |
|
---|
729 | if (!TEST_int_eq(BIO_ADDR_family(addr3), AF_INET))
|
---|
730 | goto err;
|
---|
731 |
|
---|
732 | if (!TEST_int_eq(BIO_ADDR_rawport(addr3), 2345))
|
---|
733 | goto err;
|
---|
734 |
|
---|
735 | if (!TEST_int_eq(BIO_ADDR_family(addr4), AF_INET))
|
---|
736 | goto err;
|
---|
737 |
|
---|
738 | if (!TEST_int_eq(BIO_ADDR_rawport(addr4), 1234))
|
---|
739 | goto err;
|
---|
740 |
|
---|
741 | /* test truncation, pending */
|
---|
742 | r = BIO_write(bio1, scratch, 64);
|
---|
743 | if (!TEST_int_eq(r, 64))
|
---|
744 | goto err;
|
---|
745 |
|
---|
746 | memset(scratch2, 0, 64);
|
---|
747 | if (!TEST_int_eq(BIO_dgram_set_no_trunc(bio2, 1), 1))
|
---|
748 | goto err;
|
---|
749 |
|
---|
750 | if (!TEST_int_eq(BIO_read(bio2, scratch2, 32), -1))
|
---|
751 | goto err;
|
---|
752 |
|
---|
753 | if (!TEST_int_eq(BIO_pending(bio2), 64))
|
---|
754 | goto err;
|
---|
755 |
|
---|
756 | if (!TEST_int_eq(BIO_dgram_set_no_trunc(bio2, 0), 1))
|
---|
757 | goto err;
|
---|
758 |
|
---|
759 | if (!TEST_int_eq(BIO_read(bio2, scratch2, 32), 32))
|
---|
760 | goto err;
|
---|
761 |
|
---|
762 | if (!TEST_mem_eq(scratch, 32, scratch2, 32))
|
---|
763 | goto err;
|
---|
764 |
|
---|
765 | testresult = 1;
|
---|
766 | err:
|
---|
767 | if (idx == 0)
|
---|
768 | BIO_free(bio1);
|
---|
769 | BIO_free(bio2);
|
---|
770 | BIO_ADDR_free(addr1);
|
---|
771 | BIO_ADDR_free(addr2);
|
---|
772 | BIO_ADDR_free(addr3);
|
---|
773 | BIO_ADDR_free(addr4);
|
---|
774 | return testresult;
|
---|
775 | }
|
---|
776 | # endif /* !defined(OPENSSL_NO_CHACHA) */
|
---|
777 | #endif /* !defined(OPENSSL_NO_DGRAM) && !defined(OPENSSL_NO_SOCK) */
|
---|
778 |
|
---|
779 | int setup_tests(void)
|
---|
780 | {
|
---|
781 | if (!test_skip_common_options()) {
|
---|
782 | TEST_error("Error parsing test options\n");
|
---|
783 | return 0;
|
---|
784 | }
|
---|
785 |
|
---|
786 | #if !defined(OPENSSL_NO_DGRAM) && !defined(OPENSSL_NO_SOCK)
|
---|
787 | ADD_ALL_TESTS(test_bio_dgram, OSSL_NELEM(bio_dgram_cases));
|
---|
788 | # if !defined(OPENSSL_NO_CHACHA)
|
---|
789 | ADD_ALL_TESTS(test_bio_dgram_pair, 3);
|
---|
790 | # endif
|
---|
791 | #endif
|
---|
792 |
|
---|
793 | return 1;
|
---|
794 | }
|
---|