Modify ENGINE_pkey_asn1_find_str() to use a read lock instead of a write
[openssl.git] / test / quic_stream_test.c
1 /*
2  * Copyright 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 #include "internal/packet.h"
10 #include "internal/quic_stream.h"
11 #include "testutil.h"
12
13 static int compare_iov(const unsigned char *ref, size_t ref_len,
14                        const OSSL_QTX_IOVEC *iov, size_t iov_len)
15 {
16     size_t i, total_len = 0;
17     const unsigned char *cur = ref;
18
19     for (i = 0; i < iov_len; ++i)
20         total_len += iov[i].buf_len;
21
22     if (ref_len != total_len)
23         return 0;
24
25     for (i = 0; i < iov_len; ++i) {
26         if (memcmp(cur, iov[i].buf, iov[i].buf_len))
27             return 0;
28
29         cur += iov[i].buf_len;
30     }
31
32     return 1;
33 }
34
35 static const unsigned char data_1[] = {
36     0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
37     0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f
38 };
39
40 static int test_sstream_simple(void)
41 {
42     int testresult = 0;
43     QUIC_SSTREAM *sstream = NULL;
44     OSSL_QUIC_FRAME_STREAM hdr;
45     OSSL_QTX_IOVEC iov[2];
46     size_t num_iov = 0, wr = 0, i, init_size = 8192;
47
48     if (!TEST_ptr(sstream = ossl_quic_sstream_new(init_size)))
49         goto err;
50
51     /* Should not have any data yet */
52     num_iov = OSSL_NELEM(iov);
53     if (!TEST_false(ossl_quic_sstream_get_stream_frame(sstream, 0, &hdr, iov,
54                                                        &num_iov)))
55         goto err;
56
57     /* Append data */
58     if (!TEST_true(ossl_quic_sstream_append(sstream, data_1, sizeof(data_1),
59                                             &wr))
60         || !TEST_size_t_eq(wr, sizeof(data_1)))
61         goto err;
62
63     /* Read data */
64     num_iov = OSSL_NELEM(iov);
65     if (!TEST_true(ossl_quic_sstream_get_stream_frame(sstream, 0, &hdr, iov,
66                                                       &num_iov))
67         || !TEST_size_t_gt(num_iov, 0)
68         || !TEST_uint64_t_eq(hdr.offset, 0)
69         || !TEST_uint64_t_eq(hdr.len, sizeof(data_1))
70         || !TEST_false(hdr.is_fin))
71         goto err;
72
73     if (!TEST_true(compare_iov(data_1, sizeof(data_1), iov, num_iov)))
74         goto err;
75
76     /* Mark data as half transmitted */
77     if (!TEST_true(ossl_quic_sstream_mark_transmitted(sstream, 0, 7)))
78         goto err;
79
80     /* Read data */
81     num_iov = OSSL_NELEM(iov);
82     if (!TEST_true(ossl_quic_sstream_get_stream_frame(sstream, 0, &hdr, iov,
83                                                       &num_iov))
84         || !TEST_size_t_gt(num_iov, 0)
85         || !TEST_uint64_t_eq(hdr.offset, 8)
86         || !TEST_uint64_t_eq(hdr.len, sizeof(data_1) - 8)
87         || !TEST_false(hdr.is_fin))
88         goto err;
89
90     if (!TEST_true(compare_iov(data_1 + 8, sizeof(data_1) - 8, iov, num_iov)))
91         goto err;
92
93     if (!TEST_true(ossl_quic_sstream_mark_transmitted(sstream, 8, 15)))
94         goto err;
95
96     /* Read more data; should not be any more */
97     num_iov = OSSL_NELEM(iov);
98     if (!TEST_false(ossl_quic_sstream_get_stream_frame(sstream, 0, &hdr, iov,
99                                                        &num_iov)))
100         goto err;
101
102     /* Now we have lost bytes 4-6 */
103     if (!TEST_true(ossl_quic_sstream_mark_lost(sstream, 4, 6)))
104         goto err;
105
106     /* Should be able to read them */
107     num_iov = OSSL_NELEM(iov);
108     if (!TEST_true(ossl_quic_sstream_get_stream_frame(sstream, 0, &hdr, iov,
109                                                       &num_iov))
110         || !TEST_size_t_gt(num_iov, 0)
111         || !TEST_uint64_t_eq(hdr.offset, 4)
112         || !TEST_uint64_t_eq(hdr.len, 3)
113         || !TEST_false(hdr.is_fin))
114         goto err;
115
116     if (!TEST_true(compare_iov(data_1 + 4, 3, iov, num_iov)))
117         goto err;
118
119     /* Retransmit */
120     if (!TEST_true(ossl_quic_sstream_mark_transmitted(sstream, 4, 6)))
121         goto err;
122
123     /* Read more data; should not be any more */
124     num_iov = OSSL_NELEM(iov);
125     if (!TEST_false(ossl_quic_sstream_get_stream_frame(sstream, 0, &hdr, iov,
126                                                        &num_iov)))
127         goto err;
128
129     if (!TEST_size_t_eq(ossl_quic_sstream_get_buffer_used(sstream), 16))
130         goto err;
131
132     /* Data has been acknowledged, space should be not be freed yet */
133     if (!TEST_true(ossl_quic_sstream_mark_acked(sstream, 1, 7))
134         || !TEST_size_t_eq(ossl_quic_sstream_get_buffer_used(sstream), 16))
135         goto err;
136
137     /* Now data should be freed */
138     if (!TEST_true(ossl_quic_sstream_mark_acked(sstream, 0, 0))
139         || !TEST_size_t_eq(ossl_quic_sstream_get_buffer_used(sstream), 8))
140         goto err;
141
142     if (!TEST_true(ossl_quic_sstream_mark_acked(sstream, 0, 15))
143         || !TEST_size_t_eq(ossl_quic_sstream_get_buffer_used(sstream), 0))
144         goto err;
145
146     /* Now FIN */
147     ossl_quic_sstream_fin(sstream);
148
149     /* Get FIN frame */
150     for (i = 0; i < 2; ++i) {
151         num_iov = OSSL_NELEM(iov);
152         if (!TEST_true(ossl_quic_sstream_get_stream_frame(sstream, 0, &hdr, iov,
153                                                           &num_iov))
154             || !TEST_uint64_t_eq(hdr.offset, 16)
155             || !TEST_uint64_t_eq(hdr.len, 0)
156             || !TEST_true(hdr.is_fin)
157             || !TEST_size_t_eq(num_iov, 0))
158             goto err;
159     }
160
161     if (!TEST_true(ossl_quic_sstream_mark_transmitted_fin(sstream, 16)))
162         goto err;
163
164     /* Read more data; FIN should not be returned any more */
165     num_iov = OSSL_NELEM(iov);
166     if (!TEST_false(ossl_quic_sstream_get_stream_frame(sstream, 0, &hdr, iov,
167                                                        &num_iov)))
168         goto err;
169
170     /* Lose FIN frame */
171     if (!TEST_true(ossl_quic_sstream_mark_lost_fin(sstream)))
172         goto err;
173
174     /* Get FIN frame */
175     for (i = 0; i < 2; ++i) {
176         num_iov = OSSL_NELEM(iov);
177         if (!TEST_true(ossl_quic_sstream_get_stream_frame(sstream, 0, &hdr, iov,
178                                                           &num_iov))
179             || !TEST_uint64_t_eq(hdr.offset, 16)
180             || !TEST_uint64_t_eq(hdr.len, 0)
181             || !TEST_true(hdr.is_fin)
182             || !TEST_size_t_eq(num_iov, 0))
183             goto err;
184     }
185
186     if (!TEST_true(ossl_quic_sstream_mark_transmitted_fin(sstream, 16)))
187         goto err;
188
189     /* Read more data; FIN should not be returned any more */
190     num_iov = OSSL_NELEM(iov);
191     if (!TEST_false(ossl_quic_sstream_get_stream_frame(sstream, 0, &hdr, iov,
192                                                        &num_iov)))
193         goto err;
194
195     /* Acknowledge fin. */
196     if (!TEST_true(ossl_quic_sstream_mark_acked_fin(sstream)))
197         goto err;
198
199     testresult = 1;
200  err:
201     ossl_quic_sstream_free(sstream);
202     return testresult;
203 }
204
205 static int test_sstream_bulk(int idx)
206 {
207     int testresult = 0;
208     QUIC_SSTREAM *sstream = NULL;
209     OSSL_QUIC_FRAME_STREAM hdr;
210     OSSL_QTX_IOVEC iov[2];
211     size_t i, num_iov = 0, init_size = 8192, l;
212     size_t consumed = 0, rd, expected = 0;
213     unsigned char *src_buf = NULL, *dst_buf = NULL;
214     unsigned char *ref_src_buf = NULL, *ref_dst_buf = NULL;
215     unsigned char *ref_dst_cur, *ref_src_cur, *dst_cur;
216
217     if (!TEST_ptr(sstream = ossl_quic_sstream_new(init_size)))
218         goto err;
219
220     if (!TEST_size_t_eq(ossl_quic_sstream_get_buffer_size(sstream), init_size))
221         goto err;
222
223     if (!TEST_ptr(src_buf = OPENSSL_zalloc(init_size)))
224         goto err;
225
226     if (!TEST_ptr(dst_buf = OPENSSL_malloc(init_size)))
227         goto err;
228
229     if (!TEST_ptr(ref_src_buf = OPENSSL_malloc(init_size)))
230         goto err;
231
232     if (!TEST_ptr(ref_dst_buf = OPENSSL_malloc(init_size)))
233         goto err;
234
235     /*
236      * Append a preliminary buffer to allow later code to exercise wraparound.
237      */
238     if (!TEST_true(ossl_quic_sstream_append(sstream, src_buf, init_size / 2,
239                                             &consumed))
240         || !TEST_size_t_eq(consumed, init_size / 2)
241         || !TEST_true(ossl_quic_sstream_mark_transmitted(sstream, 0,
242                                                          init_size / 2 - 1))
243         || !TEST_true(ossl_quic_sstream_mark_acked(sstream, 0,
244                                                    init_size / 2 - 1)))
245         goto err;
246
247     /* Generate a random buffer. */
248     for (i = 0; i < init_size; ++i)
249         src_buf[i] = (unsigned char)(test_random() & 0xFF);
250
251     /* Append bytes into the buffer in chunks of random length. */
252     ref_src_cur = ref_src_buf;
253     do {
254         l = (test_random() % init_size) + 1;
255         if (!TEST_true(ossl_quic_sstream_append(sstream, src_buf, l, &consumed)))
256             goto err;
257
258         memcpy(ref_src_cur, src_buf, consumed);
259         ref_src_cur     += consumed;
260     } while (consumed > 0);
261
262     if (!TEST_size_t_eq(ossl_quic_sstream_get_buffer_used(sstream), init_size)
263         || !TEST_size_t_eq(ossl_quic_sstream_get_buffer_avail(sstream), 0))
264         goto err;
265
266     /*
267      * Randomly select bytes out of the buffer by marking them as transmitted.
268      * Record the remaining bytes, which should be the sequence of bytes
269      * returned.
270      */
271     ref_src_cur = ref_src_buf;
272     ref_dst_cur = ref_dst_buf;
273     for (i = 0; i < consumed; ++i) {
274         if ((test_random() & 1) != 0) {
275             *ref_dst_cur++ = *ref_src_cur;
276             ++expected;
277         } else if (!TEST_true(ossl_quic_sstream_mark_transmitted(sstream, i, i)))
278             goto err;
279
280         ++ref_src_cur;
281     }
282
283     /* Exercise resize. */
284     if (!TEST_true(ossl_quic_sstream_set_buffer_size(sstream, init_size * 2))
285         || !TEST_true(ossl_quic_sstream_set_buffer_size(sstream, init_size)))
286         goto err;
287
288     /* Readout and verification. */
289     dst_cur = dst_buf;
290     for (i = 0, rd = 0; rd < expected; ++i) {
291         num_iov = OSSL_NELEM(iov);
292         if (!TEST_true(ossl_quic_sstream_get_stream_frame(sstream, i, &hdr, iov,
293                                                           &num_iov)))
294             goto err;
295
296         for (i = 0; i < num_iov; ++i) {
297             if (!TEST_size_t_le(iov[i].buf_len + rd, expected))
298                 goto err;
299
300             memcpy(dst_cur, iov[i].buf, iov[i].buf_len);
301             dst_cur += iov[i].buf_len;
302             rd      += iov[i].buf_len;
303         }
304
305         if (!TEST_uint64_t_eq(rd, hdr.len))
306             goto err;
307     }
308
309     if (!TEST_mem_eq(dst_buf, rd, ref_dst_buf, expected))
310         goto err;
311
312     testresult = 1;
313  err:
314     OPENSSL_free(src_buf);
315     OPENSSL_free(dst_buf);
316     OPENSSL_free(ref_src_buf);
317     OPENSSL_free(ref_dst_buf);
318     ossl_quic_sstream_free(sstream);
319     return testresult;
320 }
321
322 static int test_single_copy_read(QUIC_RSTREAM *qrs,
323                                  unsigned char *buf, size_t size,
324                                  size_t *readbytes, int *fin)
325 {
326     const unsigned char *record;
327     size_t rec_len;
328
329     *readbytes = 0;
330
331     for (;;) {
332         if (!ossl_quic_rstream_get_record(qrs, &record, &rec_len, fin))
333             return 0;
334         if (rec_len == 0)
335             break;
336         if (rec_len > size) {
337             rec_len = size;
338             *fin = 0;
339         }
340         memcpy(buf, record, rec_len);
341         size -= rec_len;
342         *readbytes += rec_len;
343         buf += rec_len;
344
345         if (!ossl_quic_rstream_release_record(qrs, rec_len))
346             return 0;
347         if (*fin || size == 0)
348             break;
349     }
350
351     return 1;
352 }
353
354 static const unsigned char simple_data[] =
355     "Hello world! And thank you for all the fish!";
356
357 static int test_rstream_simple(int idx)
358 {
359     QUIC_RSTREAM *rstream = NULL;
360     int ret = 0;
361     unsigned char buf[sizeof(simple_data)];
362     size_t readbytes = 0, avail = 0;
363     int fin = 0;
364     int use_rbuf = idx > 1;
365     int use_sc = idx % 2;
366     int (* read_fn)(QUIC_RSTREAM *, unsigned char *, size_t, size_t *,
367                     int *) = use_sc ? test_single_copy_read
368                                     : ossl_quic_rstream_read;
369
370     if (!TEST_ptr(rstream = ossl_quic_rstream_new(NULL, NULL, 0)))
371         goto err;
372
373     if (!TEST_true(ossl_quic_rstream_queue_data(rstream, NULL, 5,
374                                                 simple_data + 5, 10, 0))
375         || !TEST_true(ossl_quic_rstream_queue_data(rstream, NULL,
376                                                    sizeof(simple_data) - 1,
377                                                    simple_data + sizeof(simple_data) - 1,
378                                                    1, 1))
379         || !TEST_true(ossl_quic_rstream_peek(rstream, buf, sizeof(buf),
380                                              &readbytes, &fin))
381         || !TEST_false(fin)
382         || !TEST_size_t_eq(readbytes, 0)
383         || !TEST_true(ossl_quic_rstream_queue_data(rstream, NULL,
384                                                    sizeof(simple_data) - 10,
385                                                    simple_data + sizeof(simple_data) - 10,
386                                                    10, 1))
387         || !TEST_true(ossl_quic_rstream_queue_data(rstream, NULL, 0,
388                                                    simple_data, 1, 0))
389         || !TEST_true(ossl_quic_rstream_peek(rstream, buf, sizeof(buf),
390                                              &readbytes, &fin))
391         || !TEST_false(fin)
392         || !TEST_size_t_eq(readbytes, 1)
393         || !TEST_mem_eq(buf, 1, simple_data, 1)
394         || (use_rbuf && !TEST_false(ossl_quic_rstream_move_to_rbuf(rstream)))
395         || (use_rbuf
396             && !TEST_true(ossl_quic_rstream_resize_rbuf(rstream,
397                                                         sizeof(simple_data))))
398         || (use_rbuf && !TEST_true(ossl_quic_rstream_move_to_rbuf(rstream)))
399         || !TEST_true(ossl_quic_rstream_queue_data(rstream, NULL,
400                                                    0, simple_data,
401                                                    10, 0))
402         || !TEST_true(ossl_quic_rstream_queue_data(rstream, NULL,
403                                                    sizeof(simple_data),
404                                                    NULL,
405                                                    0, 1))
406         || !TEST_true(ossl_quic_rstream_peek(rstream, buf, sizeof(buf),
407                                              &readbytes, &fin))
408         || !TEST_false(fin)
409         || !TEST_size_t_eq(readbytes, 15)
410         || !TEST_mem_eq(buf, 15, simple_data, 15)
411         || !TEST_true(ossl_quic_rstream_queue_data(rstream, NULL,
412                                                    15,
413                                                    simple_data + 15,
414                                                    sizeof(simple_data) - 15, 1))
415         || !TEST_true(ossl_quic_rstream_available(rstream, &avail, &fin))
416         || !TEST_true(fin)
417         || !TEST_size_t_eq(avail, sizeof(simple_data))
418         || !TEST_true(read_fn(rstream, buf, 2, &readbytes, &fin))
419         || !TEST_false(fin)
420         || !TEST_size_t_eq(readbytes, 2)
421         || !TEST_mem_eq(buf, 2, simple_data, 2)
422         || !TEST_true(read_fn(rstream, buf + 2, 12, &readbytes, &fin))
423         || !TEST_false(fin)
424         || !TEST_size_t_eq(readbytes, 12)
425         || !TEST_mem_eq(buf + 2, 12, simple_data + 2, 12)
426         || !TEST_true(ossl_quic_rstream_queue_data(rstream, NULL,
427                                                    sizeof(simple_data),
428                                                    NULL,
429                                                    0, 1))
430         || (use_rbuf
431             && !TEST_true(ossl_quic_rstream_resize_rbuf(rstream,
432                                                         2 * sizeof(simple_data))))
433         || (use_rbuf && !TEST_true(ossl_quic_rstream_move_to_rbuf(rstream)))
434         || !TEST_true(read_fn(rstream, buf + 14, 5, &readbytes, &fin))
435         || !TEST_false(fin)
436         || !TEST_size_t_eq(readbytes, 5)
437         || !TEST_mem_eq(buf, 14 + 5, simple_data, 14 + 5)
438         || !TEST_true(read_fn(rstream, buf + 14 + 5, sizeof(buf) - 14 - 5,
439                               &readbytes, &fin))
440         || !TEST_true(fin)
441         || !TEST_size_t_eq(readbytes, sizeof(buf) - 14 - 5)
442         || !TEST_mem_eq(buf, sizeof(buf), simple_data, sizeof(simple_data))
443         || (use_rbuf && !TEST_true(ossl_quic_rstream_move_to_rbuf(rstream)))
444         || !TEST_true(read_fn(rstream, buf, sizeof(buf), &readbytes, &fin))
445         || !TEST_true(fin)
446         || !TEST_size_t_eq(readbytes, 0))
447         goto err;
448
449     ret = 1;
450
451  err:
452     ossl_quic_rstream_free(rstream);
453     return ret;
454 }
455
456 static int test_rstream_random(int idx)
457 {
458     unsigned char *bulk_data = NULL;
459     unsigned char *read_buf = NULL;
460     QUIC_RSTREAM *rstream = NULL;
461     size_t i, read_off, queued_min, queued_max;
462     const size_t data_size = 10000;
463     int r, s, fin = 0, fin_set = 0;
464     int ret = 0;
465     size_t readbytes = 0;
466
467     if (!TEST_ptr(bulk_data = OPENSSL_malloc(data_size))
468         || !TEST_ptr(read_buf = OPENSSL_malloc(data_size))
469         || !TEST_ptr(rstream = ossl_quic_rstream_new(NULL, NULL, 0)))
470         goto err;
471
472     for (i = 0; i < data_size; ++i)
473         bulk_data[i] = (unsigned char)(test_random() & 0xFF);
474
475     read_off = queued_min = queued_max = 0;
476     for (r = 0; r < 100; ++r) {
477         for (s = 0; s < 10; ++s) {
478             size_t off = (r * 10 + s) * 10, size = 10;
479
480             if (test_random() % 10 == 0)
481                 /* drop packet */
482                 continue;
483
484             if (off <= queued_min && off + size > queued_min)
485                 queued_min = off + size;
486
487             if (!TEST_true(ossl_quic_rstream_queue_data(rstream, NULL, off,
488                                                         bulk_data + off,
489                                                         size, 0)))
490                 goto err;
491             if (queued_max < off + size)
492                 queued_max = off + size;
493
494             if (test_random() % 5 != 0)
495                continue;
496
497             /* random overlapping retransmit */
498             off = read_off + test_random() % 50;
499             if (off > 50)
500                 off -= 50;
501             size = test_random() % 100 + 1;
502             if (off + size > data_size)
503                 off = data_size - size;
504             if (off <= queued_min && off + size > queued_min)
505                 queued_min = off + size;
506
507             if (!TEST_true(ossl_quic_rstream_queue_data(rstream, NULL, off,
508                                                         bulk_data + off,
509                                                         size, 0)))
510                 goto err;
511             if (queued_max < off + size)
512                 queued_max = off + size;
513         }
514         if (idx % 2 == 0) {
515             if (!TEST_true(test_single_copy_read(rstream, read_buf, data_size,
516                                                  &readbytes, &fin)))
517                 goto err;
518         } else if (!TEST_true(ossl_quic_rstream_read(rstream, read_buf,
519                                                      data_size,
520                                                      &readbytes, &fin))) {
521             goto err;
522         }
523         if (!TEST_size_t_ge(readbytes, queued_min - read_off)
524             || !TEST_size_t_le(readbytes + read_off, data_size)
525             || !TEST_mem_eq(read_buf, readbytes, bulk_data + read_off,
526                             readbytes))
527             goto err;
528         read_off += readbytes;
529         queued_min = read_off;
530         if (test_random() % 50 == 0)
531             if (!TEST_true(ossl_quic_rstream_resize_rbuf(rstream,
532                                                          queued_max - read_off + 1))
533                 || !TEST_true(ossl_quic_rstream_move_to_rbuf(rstream)))
534                 goto err;
535         if (!fin_set && queued_max >= data_size - test_random() % 200) {
536             fin_set = 1;
537             /* Queue empty fin frame */
538             if (!TEST_true(ossl_quic_rstream_queue_data(rstream, NULL, data_size,
539                                                         NULL, 0, 1)))
540                 goto err;
541         }
542     }
543
544     TEST_info("Total read bytes: %zu Fin rcvd: %d", read_off, fin);
545
546     if (read_off == data_size && fin_set && !fin) {
547         /* We might still receive the final empty frame */
548         if (idx % 2 == 0) {
549             if (!TEST_true(test_single_copy_read(rstream, read_buf, data_size,
550                                                  &readbytes, &fin)))
551                 goto err;
552         } else if (!TEST_true(ossl_quic_rstream_read(rstream, read_buf,
553                                                      data_size,
554                                                      &readbytes, &fin))) {
555             goto err;
556         }
557         if (!TEST_size_t_eq(readbytes, 0) || !TEST_true(fin))
558             goto err;
559     }
560
561     ret = 1;
562
563  err:
564     OPENSSL_free(bulk_data);
565     OPENSSL_free(read_buf);
566     ossl_quic_rstream_free(rstream);
567     return ret;
568 }
569
570 int setup_tests(void)
571 {
572     ADD_TEST(test_sstream_simple);
573     ADD_ALL_TESTS(test_sstream_bulk, 100);
574     ADD_ALL_TESTS(test_rstream_simple, 4);
575     ADD_ALL_TESTS(test_rstream_random, 100);
576     return 1;
577 }