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