xref: /src/crypto/openssl/test/wpackettest.c (revision f25b8c9fb4f58cf61adb47d7570abe7caa6d385d)
1 /*
2  * Copyright 2016-2025 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/buffer.h>
12 #include <openssl/rand.h>
13 #include "internal/packet_quic.h"
14 #include "testutil.h"
15 
16 static const unsigned char simple1[] = { 0xff };
17 static const unsigned char simple2[] = { 0x01, 0xff };
18 static const unsigned char simple3[] = { 0x00, 0x00, 0x00, 0x01, 0xff };
19 static const unsigned char nestedsub[] = { 0x03, 0xff, 0x01, 0xff };
20 static const unsigned char seqsub[] = { 0x01, 0xff, 0x01, 0xff };
21 static const unsigned char empty[] = { 0x00 };
22 static const unsigned char alloc[] = { 0x02, 0xfe, 0xff };
23 static const unsigned char submem[] = { 0x03, 0x02, 0xfe, 0xff };
24 static const unsigned char fixed[] = { 0xff, 0xff, 0xff };
25 static const unsigned char simpleder[] = {
26     0xfc, 0x04, 0x00, 0x01, 0x02, 0x03, 0xff, 0xfe, 0xfd
27 };
28 
29 #ifndef OPENSSL_NO_QUIC
30 
31 /* QUIC sub-packet with 4-byte length prefix, containing a 1-byte vlint */
32 static const unsigned char quic1[] = { 0x80, 0x00, 0x00, 0x01, 0x09 };
33 /* QUIC sub-packet with 1-byte length prefix, containing a 1-byte vlint */
34 static const unsigned char quic2[] = { 0x01, 0x09 };
35 /* QUIC sub-packet with 2-byte length prefix, containing a 2-byte vlint */
36 static const unsigned char quic3[] = { 0x40, 0x02, 0x40, 0x41 };
37 /* QUIC sub-packet with 8-byte length prefix, containing a 4-byte vlint */
38 static const unsigned char quic4[] = {
39     0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
40     0x80, 0x01, 0x3c, 0x6a
41 };
42 /* QUIC sub-packet with 8-byte length prefix, containing a 8-byte vlint */
43 static const unsigned char quic5[] = {
44     0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
45     0xef, 0x77, 0x21, 0x3f, 0x3f, 0x50, 0x5b, 0xa5
46 };
47 /* QUIC sub-packet, length known up-front */
48 static const unsigned char quic6[] = { 0x03, 0x55, 0x66, 0x77 };
49 /* Nested and sequential sub-packets with length prefixes */
50 static const unsigned char quic7[] = {
51     0x07, 0x80, 0x00, 0x00, 0x08, 0x65, 0x14, 0x40, 0x01, 0x05,
52     0x40, 0x01, 0x11, 0x40, 0x01, 0x12, 0x40, 0x01, 0x13
53 };
54 
55 #endif
56 
57 static BUF_MEM *buf;
58 
cleanup(WPACKET * pkt)59 static int cleanup(WPACKET *pkt)
60 {
61     WPACKET_cleanup(pkt);
62     return 0;
63 }
64 
test_WPACKET_init(void)65 static int test_WPACKET_init(void)
66 {
67     WPACKET pkt;
68     int i;
69     size_t written;
70     unsigned char sbuf[3];
71 
72     if (!TEST_true(WPACKET_init(&pkt, buf))
73         || !TEST_true(WPACKET_put_bytes_u8(&pkt, 0xff))
74         /* Closing a top level WPACKET should fail */
75         || !TEST_false(WPACKET_close(&pkt))
76         /* Finishing a top level WPACKET should succeed */
77         || !TEST_true(WPACKET_finish(&pkt))
78         /*
79          * Can't call close or finish on a WPACKET that's already
80          * finished.
81          */
82         || !TEST_false(WPACKET_close(&pkt))
83         || !TEST_false(WPACKET_finish(&pkt))
84         || !TEST_true(WPACKET_get_total_written(&pkt, &written))
85         || !TEST_mem_eq(buf->data, written, simple1, sizeof(simple1)))
86         return cleanup(&pkt);
87 
88     /* Now try with a one byte length prefix */
89     if (!TEST_true(WPACKET_init_len(&pkt, buf, 1))
90         || !TEST_true(WPACKET_put_bytes_u8(&pkt, 0xff))
91         || !TEST_true(WPACKET_finish(&pkt))
92         || !TEST_true(WPACKET_get_total_written(&pkt, &written))
93         || !TEST_mem_eq(buf->data, written, simple2, sizeof(simple2)))
94         return cleanup(&pkt);
95 
96     /* And a longer length prefix */
97     if (!TEST_true(WPACKET_init_len(&pkt, buf, 4))
98         || !TEST_true(WPACKET_put_bytes_u8(&pkt, 0xff))
99         || !TEST_true(WPACKET_finish(&pkt))
100         || !TEST_true(WPACKET_get_total_written(&pkt, &written))
101         || !TEST_mem_eq(buf->data, written, simple3, sizeof(simple3)))
102         return cleanup(&pkt);
103 
104     if (!TEST_true(WPACKET_init_len(&pkt, buf, 1)))
105         return cleanup(&pkt);
106     for (i = 1; i < 257; i++) {
107         /*
108          * Putting more bytes in than fit for the size of the length prefix
109          * should fail
110          */
111         if (!TEST_int_eq(WPACKET_put_bytes_u8(&pkt, 0xff), i < 256))
112             return cleanup(&pkt);
113     }
114     if (!TEST_true(WPACKET_finish(&pkt)))
115         return cleanup(&pkt);
116 
117     /* Test initialising from a fixed size buffer */
118     if (!TEST_true(WPACKET_init_static_len(&pkt, sbuf, sizeof(sbuf), 0))
119         /* Adding 3 bytes should succeed */
120         || !TEST_true(WPACKET_put_bytes_u24(&pkt, 0xffffff))
121         /* Adding 1 more byte should fail */
122         || !TEST_false(WPACKET_put_bytes_u8(&pkt, 0xff))
123         /* Finishing the top level WPACKET should succeed */
124         || !TEST_true(WPACKET_finish(&pkt))
125         || !TEST_true(WPACKET_get_total_written(&pkt, &written))
126         || !TEST_mem_eq(sbuf, written, fixed, sizeof(sbuf))
127         /* Initialise with 1 len byte */
128         || !TEST_true(WPACKET_init_static_len(&pkt, sbuf, sizeof(sbuf), 1))
129         /* Adding 2 bytes should succeed */
130         || !TEST_true(WPACKET_put_bytes_u16(&pkt, 0xfeff))
131         /* Adding 1 more byte should fail */
132         || !TEST_false(WPACKET_put_bytes_u8(&pkt, 0xff))
133         || !TEST_true(WPACKET_finish(&pkt))
134         || !TEST_true(WPACKET_get_total_written(&pkt, &written))
135         || !TEST_mem_eq(sbuf, written, alloc, sizeof(alloc)))
136         return cleanup(&pkt);
137 
138     return 1;
139 }
140 
test_WPACKET_set_max_size(void)141 static int test_WPACKET_set_max_size(void)
142 {
143     WPACKET pkt;
144     size_t written;
145 
146     if (!TEST_true(WPACKET_init(&pkt, buf))
147         /*
148          * No previous lenbytes set so we should be ok to set the max
149          * possible max size
150          */
151         || !TEST_true(WPACKET_set_max_size(&pkt, SIZE_MAX))
152         /* We should be able to set it smaller too */
153         || !TEST_true(WPACKET_set_max_size(&pkt, SIZE_MAX - 1))
154         /* And setting it bigger again should be ok */
155         || !TEST_true(WPACKET_set_max_size(&pkt, SIZE_MAX))
156         || !TEST_true(WPACKET_finish(&pkt)))
157         return cleanup(&pkt);
158 
159     if (!TEST_true(WPACKET_init_len(&pkt, buf, 1))
160         /*
161          * Should fail because we already consumed 1 byte with the
162          * length
163          */
164         || !TEST_false(WPACKET_set_max_size(&pkt, 0))
165         /*
166          * Max size can't be bigger than biggest that will fit in
167          * lenbytes
168          */
169         || !TEST_false(WPACKET_set_max_size(&pkt, 0x0101))
170         /* It can be the same as the maximum possible size */
171         || !TEST_true(WPACKET_set_max_size(&pkt, 0x0100))
172         /* Or it can be less */
173         || !TEST_true(WPACKET_set_max_size(&pkt, 0x01))
174         /* Should fail because packet is already filled */
175         || !TEST_false(WPACKET_put_bytes_u8(&pkt, 0xff))
176         /* You can't put in more bytes than max size */
177         || !TEST_true(WPACKET_set_max_size(&pkt, 0x02))
178         || !TEST_true(WPACKET_put_bytes_u8(&pkt, 0xff))
179         || !TEST_false(WPACKET_put_bytes_u8(&pkt, 0xff))
180         || !TEST_true(WPACKET_finish(&pkt))
181         || !TEST_true(WPACKET_get_total_written(&pkt, &written))
182         || !TEST_mem_eq(buf->data, written, simple2, sizeof(simple2)))
183         return cleanup(&pkt);
184 
185     return 1;
186 }
187 
test_WPACKET_start_sub_packet(void)188 static int test_WPACKET_start_sub_packet(void)
189 {
190     WPACKET pkt;
191     size_t written;
192     size_t len;
193 
194     if (!TEST_true(WPACKET_init(&pkt, buf))
195         || !TEST_true(WPACKET_start_sub_packet(&pkt))
196         || !TEST_true(WPACKET_put_bytes_u8(&pkt, 0xff))
197         /* Can't finish because we have a sub packet */
198         || !TEST_false(WPACKET_finish(&pkt))
199         || !TEST_true(WPACKET_close(&pkt))
200         /* Sub packet is closed so can't close again */
201         || !TEST_false(WPACKET_close(&pkt))
202         /* Now a top level so finish should succeed */
203         || !TEST_true(WPACKET_finish(&pkt))
204         || !TEST_true(WPACKET_get_total_written(&pkt, &written))
205         || !TEST_mem_eq(buf->data, written, simple1, sizeof(simple1)))
206         return cleanup(&pkt);
207 
208     /* Single sub-packet with length prefix */
209     if (!TEST_true(WPACKET_init(&pkt, buf))
210         || !TEST_true(WPACKET_start_sub_packet_u8(&pkt))
211         || !TEST_true(WPACKET_put_bytes_u8(&pkt, 0xff))
212         || !TEST_true(WPACKET_close(&pkt))
213         || !TEST_true(WPACKET_finish(&pkt))
214         || !TEST_true(WPACKET_get_total_written(&pkt, &written))
215         || !TEST_mem_eq(buf->data, written, simple2, sizeof(simple2)))
216         return cleanup(&pkt);
217 
218     /* Nested sub-packets with length prefixes */
219     if (!TEST_true(WPACKET_init(&pkt, buf))
220         || !TEST_true(WPACKET_start_sub_packet_u8(&pkt))
221         || !TEST_true(WPACKET_put_bytes_u8(&pkt, 0xff))
222         || !TEST_true(WPACKET_start_sub_packet_u8(&pkt))
223         || !TEST_true(WPACKET_put_bytes_u8(&pkt, 0xff))
224         || !TEST_true(WPACKET_get_length(&pkt, &len))
225         || !TEST_size_t_eq(len, 1)
226         || !TEST_true(WPACKET_close(&pkt))
227         || !TEST_true(WPACKET_get_length(&pkt, &len))
228         || !TEST_size_t_eq(len, 3)
229         || !TEST_true(WPACKET_close(&pkt))
230         || !TEST_true(WPACKET_finish(&pkt))
231         || !TEST_true(WPACKET_get_total_written(&pkt, &written))
232         || !TEST_mem_eq(buf->data, written, nestedsub, sizeof(nestedsub)))
233         return cleanup(&pkt);
234 
235     /* Sequential sub-packets with length prefixes */
236     if (!TEST_true(WPACKET_init(&pkt, buf))
237         || !TEST_true(WPACKET_start_sub_packet_u8(&pkt))
238         || !TEST_true(WPACKET_put_bytes_u8(&pkt, 0xff))
239         || !TEST_true(WPACKET_close(&pkt))
240         || !TEST_true(WPACKET_start_sub_packet_u8(&pkt))
241         || !TEST_true(WPACKET_put_bytes_u8(&pkt, 0xff))
242         || !TEST_true(WPACKET_close(&pkt))
243         || !TEST_true(WPACKET_finish(&pkt))
244         || !TEST_true(WPACKET_get_total_written(&pkt, &written))
245         || !TEST_mem_eq(buf->data, written, seqsub, sizeof(seqsub)))
246         return cleanup(&pkt);
247 
248     /* Nested sub-packets with lengths filled before finish */
249     if (!TEST_true(WPACKET_init(&pkt, buf))
250         || !TEST_true(WPACKET_start_sub_packet_u8(&pkt))
251         || !TEST_true(WPACKET_put_bytes_u8(&pkt, 0xff))
252         || !TEST_true(WPACKET_start_sub_packet_u8(&pkt))
253         || !TEST_true(WPACKET_put_bytes_u8(&pkt, 0xff))
254         || !TEST_true(WPACKET_get_length(&pkt, &len))
255         || !TEST_size_t_eq(len, 1)
256         || !TEST_true(WPACKET_close(&pkt))
257         || !TEST_true(WPACKET_get_length(&pkt, &len))
258         || !TEST_size_t_eq(len, 3)
259         || !TEST_true(WPACKET_close(&pkt))
260         || !TEST_true(WPACKET_fill_lengths(&pkt))
261         || !TEST_true(WPACKET_get_total_written(&pkt, &written))
262         || !TEST_mem_eq(buf->data, written, nestedsub, sizeof(nestedsub))
263         || !TEST_true(WPACKET_finish(&pkt)))
264         return cleanup(&pkt);
265 
266     return 1;
267 }
268 
test_WPACKET_set_flags(void)269 static int test_WPACKET_set_flags(void)
270 {
271     WPACKET pkt;
272     size_t written;
273 
274     /* Set packet to be non-zero length */
275     if (!TEST_true(WPACKET_init(&pkt, buf))
276         || !TEST_true(WPACKET_set_flags(&pkt, WPACKET_FLAGS_NON_ZERO_LENGTH))
277         /* Should fail because of zero length */
278         || !TEST_false(WPACKET_finish(&pkt))
279         || !TEST_true(WPACKET_put_bytes_u8(&pkt, 0xff))
280         || !TEST_true(WPACKET_finish(&pkt))
281         || !TEST_true(WPACKET_get_total_written(&pkt, &written))
282         || !TEST_mem_eq(buf->data, written, simple1, sizeof(simple1)))
283         return cleanup(&pkt);
284 
285     /* Repeat above test in a sub-packet */
286     if (!TEST_true(WPACKET_init(&pkt, buf))
287         || !TEST_true(WPACKET_start_sub_packet(&pkt))
288         || !TEST_true(WPACKET_set_flags(&pkt, WPACKET_FLAGS_NON_ZERO_LENGTH))
289         /* Should fail because of zero length */
290         || !TEST_false(WPACKET_close(&pkt))
291         || !TEST_true(WPACKET_put_bytes_u8(&pkt, 0xff))
292         || !TEST_true(WPACKET_close(&pkt))
293         || !TEST_true(WPACKET_finish(&pkt))
294         || !TEST_true(WPACKET_get_total_written(&pkt, &written))
295         || !TEST_mem_eq(buf->data, written, simple1, sizeof(simple1)))
296         return cleanup(&pkt);
297 
298     /* Set packet to abandon non-zero length */
299     if (!TEST_true(WPACKET_init_len(&pkt, buf, 1))
300         || !TEST_true(WPACKET_set_flags(&pkt, WPACKET_FLAGS_ABANDON_ON_ZERO_LENGTH))
301         || !TEST_true(WPACKET_finish(&pkt))
302         || !TEST_true(WPACKET_get_total_written(&pkt, &written))
303         || !TEST_size_t_eq(written, 0))
304         return cleanup(&pkt);
305 
306     /* Repeat above test but only abandon a sub-packet */
307     if (!TEST_true(WPACKET_init_len(&pkt, buf, 1))
308         || !TEST_true(WPACKET_start_sub_packet_u8(&pkt))
309         || !TEST_true(WPACKET_set_flags(&pkt, WPACKET_FLAGS_ABANDON_ON_ZERO_LENGTH))
310         || !TEST_true(WPACKET_close(&pkt))
311         || !TEST_true(WPACKET_finish(&pkt))
312         || !TEST_true(WPACKET_get_total_written(&pkt, &written))
313         || !TEST_mem_eq(buf->data, written, empty, sizeof(empty)))
314         return cleanup(&pkt);
315 
316     /* And repeat with a non empty sub-packet */
317     if (!TEST_true(WPACKET_init(&pkt, buf))
318         || !TEST_true(WPACKET_start_sub_packet_u8(&pkt))
319         || !TEST_true(WPACKET_set_flags(&pkt, WPACKET_FLAGS_ABANDON_ON_ZERO_LENGTH))
320         || !TEST_true(WPACKET_put_bytes_u8(&pkt, 0xff))
321         || !TEST_true(WPACKET_close(&pkt))
322         || !TEST_true(WPACKET_finish(&pkt))
323         || !TEST_true(WPACKET_get_total_written(&pkt, &written))
324         || !TEST_mem_eq(buf->data, written, simple2, sizeof(simple2)))
325         return cleanup(&pkt);
326     return 1;
327 }
328 
test_WPACKET_allocate_bytes(void)329 static int test_WPACKET_allocate_bytes(void)
330 {
331     WPACKET pkt;
332     size_t written;
333     unsigned char *bytes;
334 
335     if (!TEST_true(WPACKET_init_len(&pkt, buf, 1))
336         || !TEST_true(WPACKET_allocate_bytes(&pkt, 2, &bytes)))
337         return cleanup(&pkt);
338     bytes[0] = 0xfe;
339     bytes[1] = 0xff;
340     if (!TEST_true(WPACKET_finish(&pkt))
341         || !TEST_true(WPACKET_get_total_written(&pkt, &written))
342         || !TEST_mem_eq(buf->data, written, alloc, sizeof(alloc)))
343         return cleanup(&pkt);
344 
345     /* Repeat with WPACKET_sub_allocate_bytes */
346     if (!TEST_true(WPACKET_init_len(&pkt, buf, 1))
347         || !TEST_true(WPACKET_sub_allocate_bytes_u8(&pkt, 2, &bytes)))
348         return cleanup(&pkt);
349     bytes[0] = 0xfe;
350     bytes[1] = 0xff;
351     if (!TEST_true(WPACKET_finish(&pkt))
352         || !TEST_true(WPACKET_get_total_written(&pkt, &written))
353         || !TEST_mem_eq(buf->data, written, submem, sizeof(submem)))
354         return cleanup(&pkt);
355 
356     return 1;
357 }
358 
test_WPACKET_memcpy(void)359 static int test_WPACKET_memcpy(void)
360 {
361     WPACKET pkt;
362     size_t written;
363     const unsigned char bytes[] = { 0xfe, 0xff };
364 
365     if (!TEST_true(WPACKET_init_len(&pkt, buf, 1))
366         || !TEST_true(WPACKET_memcpy(&pkt, bytes, sizeof(bytes)))
367         || !TEST_true(WPACKET_finish(&pkt))
368         || !TEST_true(WPACKET_get_total_written(&pkt, &written))
369         || !TEST_mem_eq(buf->data, written, alloc, sizeof(alloc)))
370         return cleanup(&pkt);
371 
372     /* Repeat with WPACKET_sub_memcpy() */
373     if (!TEST_true(WPACKET_init_len(&pkt, buf, 1))
374         || !TEST_true(WPACKET_sub_memcpy_u8(&pkt, bytes, sizeof(bytes)))
375         || !TEST_true(WPACKET_finish(&pkt))
376         || !TEST_true(WPACKET_get_total_written(&pkt, &written))
377         || !TEST_mem_eq(buf->data, written, submem, sizeof(submem)))
378         return cleanup(&pkt);
379 
380     return 1;
381 }
382 
test_WPACKET_init_der(void)383 static int test_WPACKET_init_der(void)
384 {
385     WPACKET pkt;
386     unsigned char sbuf[1024];
387     unsigned char testdata[] = { 0x00, 0x01, 0x02, 0x03 };
388     unsigned char testdata2[259] = { 0x82, 0x01, 0x00 };
389     size_t written[2];
390     size_t size1, size2;
391     int flags = WPACKET_FLAGS_ABANDON_ON_ZERO_LENGTH;
392     int i;
393 
394     /* Test initialising for writing DER */
395     if (!TEST_true(WPACKET_init_der(&pkt, sbuf, sizeof(sbuf)))
396         || !TEST_true(WPACKET_put_bytes_u24(&pkt, 0xfffefd))
397         /* Test writing data in a length prefixed sub-packet */
398         || !TEST_true(WPACKET_start_sub_packet(&pkt))
399         || !TEST_true(WPACKET_memcpy(&pkt, testdata, sizeof(testdata)))
400         || !TEST_true(WPACKET_close(&pkt))
401         || !TEST_true(WPACKET_put_bytes_u8(&pkt, 0xfc))
402         /* this sub-packet is empty, and should render zero bytes */
403         || (!TEST_true(WPACKET_start_sub_packet(&pkt))
404             || !TEST_true(WPACKET_set_flags(&pkt, flags))
405             || !TEST_true(WPACKET_get_total_written(&pkt, &size1))
406             || !TEST_true(WPACKET_close(&pkt))
407             || !TEST_true(WPACKET_get_total_written(&pkt, &size2))
408             || !TEST_size_t_eq(size1, size2))
409         || !TEST_true(WPACKET_finish(&pkt))
410         || !TEST_true(WPACKET_get_total_written(&pkt, &written[0]))
411         || !TEST_mem_eq(WPACKET_get_curr(&pkt), written[0], simpleder,
412             sizeof(simpleder)))
413         return cleanup(&pkt);
414 
415     /* Generate random packet data for test */
416     if (!TEST_int_gt(RAND_bytes(&testdata2[3], sizeof(testdata2) - 3), 0))
417         return 0;
418 
419     /*
420      * Test with a sub-packet that has 2 length bytes. We do 2 passes - first
421      * with a NULL buffer, just to calculate lengths, and a second pass with a
422      * real buffer to actually generate a packet
423      */
424     for (i = 0; i < 2; i++) {
425         if (i == 0) {
426             if (!TEST_true(WPACKET_init_null_der(&pkt)))
427                 return 0;
428         } else {
429             if (!TEST_true(WPACKET_init_der(&pkt, sbuf, sizeof(sbuf))))
430                 return 0;
431         }
432         if (!TEST_true(WPACKET_start_sub_packet(&pkt))
433             || !TEST_true(WPACKET_memcpy(&pkt, &testdata2[3],
434                 sizeof(testdata2) - 3))
435             || !TEST_true(WPACKET_close(&pkt))
436             || !TEST_true(WPACKET_finish(&pkt))
437             || !TEST_true(WPACKET_get_total_written(&pkt, &written[i])))
438             return cleanup(&pkt);
439     }
440 
441     /*
442      * Check that the size calculated in the first pass equals the size of the
443      * packet actually generated in the second pass. Also check the generated
444      * packet looks as we expect it to.
445      */
446     if (!TEST_size_t_eq(written[0], written[1])
447         || !TEST_mem_eq(WPACKET_get_curr(&pkt), written[1], testdata2,
448             sizeof(testdata2)))
449         return 0;
450 
451     return 1;
452 }
453 
454 #ifndef OPENSSL_NO_QUIC
455 
test_WPACKET_quic(void)456 static int test_WPACKET_quic(void)
457 {
458     WPACKET pkt;
459     size_t written, len;
460     unsigned char *bytes;
461 
462     /* QUIC sub-packet with 4-byte length prefix, containing a 1-byte vlint */
463     if (!TEST_true(WPACKET_init(&pkt, buf))
464         || !TEST_true(WPACKET_start_quic_sub_packet(&pkt))
465         || !TEST_true(WPACKET_quic_write_vlint(&pkt, 0x09))
466         /* Can't finish because we have a sub packet */
467         || !TEST_false(WPACKET_finish(&pkt))
468         || !TEST_true(WPACKET_close(&pkt))
469         /* Sub packet is closed so can't close again */
470         || !TEST_false(WPACKET_close(&pkt))
471         /* Now a top level so finish should succeed */
472         || !TEST_true(WPACKET_finish(&pkt))
473         || !TEST_true(WPACKET_get_total_written(&pkt, &written))
474         || !TEST_mem_eq(buf->data, written, quic1, sizeof(quic1)))
475         return cleanup(&pkt);
476 
477     /* QUIC sub-packet with 1-byte length prefix, containing a 1-byte vlint */
478     if (!TEST_true(WPACKET_init(&pkt, buf))
479         || !TEST_true(WPACKET_start_quic_sub_packet_bound(&pkt, OSSL_QUIC_VLINT_1B_MAX))
480         || !TEST_true(WPACKET_quic_write_vlint(&pkt, 0x09))
481         || !TEST_false(WPACKET_finish(&pkt))
482         || !TEST_true(WPACKET_close(&pkt))
483         || !TEST_false(WPACKET_close(&pkt))
484         || !TEST_true(WPACKET_finish(&pkt))
485         || !TEST_true(WPACKET_get_total_written(&pkt, &written))
486         || !TEST_mem_eq(buf->data, written, quic2, sizeof(quic2)))
487         return cleanup(&pkt);
488 
489     /* QUIC sub-packet with 2-byte length prefix, containing a 2-byte vlint */
490     if (!TEST_true(WPACKET_init(&pkt, buf))
491         || !TEST_true(WPACKET_start_quic_sub_packet_bound(&pkt, OSSL_QUIC_VLINT_2B_MIN))
492         || !TEST_true(WPACKET_quic_write_vlint(&pkt, 0x41))
493         || !TEST_false(WPACKET_finish(&pkt))
494         || !TEST_true(WPACKET_close(&pkt))
495         || !TEST_false(WPACKET_close(&pkt))
496         || !TEST_true(WPACKET_finish(&pkt))
497         || !TEST_true(WPACKET_get_total_written(&pkt, &written))
498         || !TEST_mem_eq(buf->data, written, quic3, sizeof(quic3)))
499         return cleanup(&pkt);
500 
501     /* QUIC sub-packet with 8-byte length prefix, containing a 4-byte vlint */
502     if (!TEST_true(WPACKET_init(&pkt, buf))
503         || !TEST_true(WPACKET_start_quic_sub_packet_bound(&pkt, OSSL_QUIC_VLINT_8B_MIN))
504         || !TEST_true(WPACKET_quic_write_vlint(&pkt, 0x13c6a))
505         || !TEST_false(WPACKET_finish(&pkt))
506         || !TEST_true(WPACKET_close(&pkt))
507         || !TEST_false(WPACKET_close(&pkt))
508         || !TEST_true(WPACKET_finish(&pkt))
509         || !TEST_true(WPACKET_get_total_written(&pkt, &written))
510         || !TEST_mem_eq(buf->data, written, quic4, sizeof(quic4)))
511         return cleanup(&pkt);
512 
513     /* QUIC sub-packet with 8-byte length prefix, containing a 8-byte vlint */
514     if (!TEST_true(WPACKET_init(&pkt, buf))
515         || !TEST_true(WPACKET_start_quic_sub_packet_bound(&pkt, OSSL_QUIC_VLINT_8B_MIN))
516         || !TEST_true(WPACKET_quic_write_vlint(&pkt, 0x2f77213f3f505ba5ULL))
517         || !TEST_false(WPACKET_finish(&pkt))
518         || !TEST_true(WPACKET_close(&pkt))
519         || !TEST_false(WPACKET_close(&pkt))
520         || !TEST_true(WPACKET_finish(&pkt))
521         || !TEST_true(WPACKET_get_total_written(&pkt, &written))
522         || !TEST_mem_eq(buf->data, written, quic5, sizeof(quic5)))
523         return cleanup(&pkt);
524 
525     /* QUIC sub-packet, length known up-front */
526     if (!TEST_true(WPACKET_init(&pkt, buf))
527         || !TEST_true(WPACKET_quic_sub_allocate_bytes(&pkt, 3, &bytes)))
528         return cleanup(&pkt);
529 
530     bytes[0] = 0x55;
531     bytes[1] = 0x66;
532     bytes[2] = 0x77;
533 
534     if (!TEST_true(WPACKET_finish(&pkt))
535         || !TEST_true(WPACKET_get_total_written(&pkt, &written))
536         || !TEST_mem_eq(buf->data, written, quic6, sizeof(quic6)))
537         return cleanup(&pkt);
538 
539     /* Nested and sequential sub-packets with length prefixes */
540     if (!TEST_true(WPACKET_init(&pkt, buf))
541         || !TEST_true(WPACKET_quic_write_vlint(&pkt, 0x07))
542         || !TEST_true(WPACKET_get_length(&pkt, &len))
543         || !TEST_size_t_eq(len, 1)
544         || !TEST_true(WPACKET_start_quic_sub_packet_bound(&pkt, OSSL_QUIC_VLINT_4B_MIN))
545         || !TEST_true(WPACKET_quic_write_vlint(&pkt, 0x2514))
546         || !TEST_true(WPACKET_get_length(&pkt, &len))
547         || !TEST_size_t_eq(len, 2)
548         || !TEST_true(WPACKET_start_quic_sub_packet_bound(&pkt, OSSL_QUIC_VLINT_2B_MIN))
549         || !TEST_true(WPACKET_quic_write_vlint(&pkt, 0x05))
550         || !TEST_true(WPACKET_get_length(&pkt, &len))
551         || !TEST_size_t_eq(len, 1)
552         || !TEST_true(WPACKET_close(&pkt))
553         || !TEST_true(WPACKET_start_quic_sub_packet_bound(&pkt, OSSL_QUIC_VLINT_2B_MIN))
554         || !TEST_true(WPACKET_quic_write_vlint(&pkt, 0x11))
555         || !TEST_true(WPACKET_close(&pkt))
556         || !TEST_true(WPACKET_get_length(&pkt, &len))
557         || !TEST_size_t_eq(len, 8)
558         || !TEST_true(WPACKET_close(&pkt))
559         || !TEST_true(WPACKET_start_quic_sub_packet_bound(&pkt, OSSL_QUIC_VLINT_2B_MIN))
560         || !TEST_true(WPACKET_quic_write_vlint(&pkt, 0x12))
561         || !TEST_true(WPACKET_close(&pkt))
562         || !TEST_true(WPACKET_start_quic_sub_packet_bound(&pkt, OSSL_QUIC_VLINT_2B_MIN))
563         || !TEST_true(WPACKET_quic_write_vlint(&pkt, 0x13))
564         || !TEST_true(WPACKET_close(&pkt))
565         || !TEST_true(WPACKET_finish(&pkt))
566         || !TEST_true(WPACKET_get_total_written(&pkt, &written))
567         || !TEST_mem_eq(buf->data, written, quic7, sizeof(quic7)))
568         return cleanup(&pkt);
569 
570     /* Trying to encode a value above OSSL_QUIC_VLINT_MAX should fail */
571     if (!TEST_true(WPACKET_init(&pkt, buf))
572         || !TEST_false(WPACKET_quic_write_vlint(&pkt, OSSL_QUIC_VLINT_MAX + 1))
573         || !TEST_true(WPACKET_quic_write_vlint(&pkt, OSSL_QUIC_VLINT_MAX)))
574         return cleanup(&pkt);
575 
576     WPACKET_cleanup(&pkt);
577     return 1;
578 }
579 
test_WPACKET_quic_vlint_random(void)580 static int test_WPACKET_quic_vlint_random(void)
581 {
582     size_t i, written;
583     uint64_t expected, actual = 0;
584     unsigned char rand_data[9];
585     WPACKET pkt;
586     PACKET read_pkt = { 0 };
587 
588     for (i = 0; i < 10000; ++i) {
589         if (!TEST_int_gt(RAND_bytes(rand_data, sizeof(rand_data)), 0))
590             return 0;
591 
592         memcpy(&expected, rand_data, sizeof(expected));
593 
594         /*
595          * Ensure that all size classes get tested with equal probability.
596          */
597         switch (rand_data[8] & 3) {
598         case 0:
599             expected &= OSSL_QUIC_VLINT_1B_MAX;
600             break;
601         case 1:
602             expected &= OSSL_QUIC_VLINT_2B_MAX;
603             break;
604         case 2:
605             expected &= OSSL_QUIC_VLINT_4B_MAX;
606             break;
607         case 3:
608             expected &= OSSL_QUIC_VLINT_8B_MAX;
609             break;
610         }
611 
612         if (!TEST_true(WPACKET_init(&pkt, buf))
613             || !TEST_true(WPACKET_quic_write_vlint(&pkt, expected))
614             || !TEST_true(WPACKET_get_total_written(&pkt, &written)))
615             return cleanup(&pkt);
616 
617         if (!TEST_true(PACKET_buf_init(&read_pkt, (unsigned char *)buf->data, written))
618             || !TEST_true(PACKET_get_quic_vlint(&read_pkt, &actual))
619             || !TEST_uint64_t_eq(expected, actual))
620             return cleanup(&pkt);
621 
622         WPACKET_cleanup(&pkt);
623     }
624 
625     WPACKET_cleanup(&pkt);
626     return 1;
627 }
628 
629 #endif
630 
setup_tests(void)631 int setup_tests(void)
632 {
633     if (!TEST_ptr(buf = BUF_MEM_new()))
634         return 0;
635 
636     ADD_TEST(test_WPACKET_init);
637     ADD_TEST(test_WPACKET_set_max_size);
638     ADD_TEST(test_WPACKET_start_sub_packet);
639     ADD_TEST(test_WPACKET_set_flags);
640     ADD_TEST(test_WPACKET_allocate_bytes);
641     ADD_TEST(test_WPACKET_memcpy);
642     ADD_TEST(test_WPACKET_init_der);
643 #ifndef OPENSSL_NO_QUIC
644     ADD_TEST(test_WPACKET_quic);
645     ADD_TEST(test_WPACKET_quic_vlint_random);
646 #endif
647     return 1;
648 }
649 
cleanup_tests(void)650 void cleanup_tests(void)
651 {
652     BUF_MEM_free(buf);
653 }
654