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