bytestringtest.c revision 1.17
1/*	$OpenBSD: bytestringtest.c,v 1.17 2023/01/01 17:43:04 miod Exp $	*/
2/*
3 * Copyright (c) 2014, Google Inc.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
14 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
15 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
16
17#include <stdio.h>
18#include <stdlib.h>
19#include <string.h>
20
21#include <openssl/crypto.h>
22
23#include "bytestring.h"
24
25/* This is from <openssl/base.h> in boringssl */
26#define OPENSSL_U64(x) x##ULL
27
28#define PRINT_ERROR printf("Error in %s [%s:%d]\n", __func__, __FILE__, \
29		__LINE__)
30
31#define CHECK(a) do {							\
32	if (!(a)) {							\
33		PRINT_ERROR;						\
34		return 0;						\
35	}								\
36} while (0)
37
38#define CHECK_GOTO(a) do {						\
39	if (!(a)) {							\
40		PRINT_ERROR;						\
41		goto err;						\
42	}								\
43} while (0)
44
45static int
46test_skip(void)
47{
48	static const uint8_t kData[] = {1, 2, 3};
49	CBS data;
50
51	CBS_init(&data, kData, sizeof(kData));
52
53	CHECK(CBS_len(&data) == 3);
54	CHECK(CBS_skip(&data, 1));
55	CHECK(CBS_len(&data) == 2);
56	CHECK(CBS_skip(&data, 2));
57	CHECK(CBS_len(&data) == 0);
58	CHECK(!CBS_skip(&data, 1));
59
60	return 1;
61}
62
63static int
64test_get_u(void)
65{
66	static const uint8_t kData[] = {
67		1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
68		11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
69	};
70	uint8_t u8;
71	uint16_t u16;
72	uint32_t u32;
73	uint64_t u64;
74	CBS data;
75
76	CBS_init(&data, kData, sizeof(kData));
77
78	CHECK(CBS_get_u8(&data, &u8));
79	CHECK(u8 == 1);
80	CHECK(CBS_get_u16(&data, &u16));
81	CHECK(u16 == 0x203);
82	CHECK(CBS_get_u24(&data, &u32));
83	CHECK(u32 == 0x40506);
84	CHECK(CBS_get_u32(&data, &u32));
85	CHECK(u32 == 0x708090a);
86	CHECK(CBS_get_u64(&data, &u64));
87	CHECK(u64 == 0x0b0c0d0e0f101112ULL);
88	CHECK(CBS_get_last_u8(&data, &u8));
89	CHECK(u8 == 20);
90	CHECK(CBS_get_last_u8(&data, &u8));
91	CHECK(u8 == 19);
92	CHECK(!CBS_get_u8(&data, &u8));
93	CHECK(!CBS_get_last_u8(&data, &u8));
94
95	return 1;
96}
97
98static int
99test_get_prefixed(void)
100{
101	static const uint8_t kData[] = {1, 2, 0, 2, 3, 4, 0, 0, 3, 3, 2, 1};
102	uint8_t u8;
103	uint16_t u16;
104	uint32_t u32;
105	CBS data, prefixed;
106
107	CBS_init(&data, kData, sizeof(kData));
108
109	CHECK(CBS_get_u8_length_prefixed(&data, &prefixed));
110	CHECK(CBS_len(&prefixed) == 1);
111	CHECK(CBS_get_u8(&prefixed, &u8));
112	CHECK(u8 == 2);
113	CHECK(CBS_get_u16_length_prefixed(&data, &prefixed));
114	CHECK(CBS_len(&prefixed) == 2);
115	CHECK(CBS_get_u16(&prefixed, &u16));
116	CHECK(u16 == 0x304);
117	CHECK(CBS_get_u24_length_prefixed(&data, &prefixed));
118	CHECK(CBS_len(&prefixed) == 3);
119	CHECK(CBS_get_u24(&prefixed, &u32));
120	CHECK(u32 == 0x30201);
121
122	return 1;
123}
124
125static int
126test_get_prefixed_bad(void)
127{
128	static const uint8_t kData1[] = {2, 1};
129	static const uint8_t kData2[] = {0, 2, 1};
130	static const uint8_t kData3[] = {0, 0, 2, 1};
131	CBS data, prefixed;
132
133	CBS_init(&data, kData1, sizeof(kData1));
134	CHECK(!CBS_get_u8_length_prefixed(&data, &prefixed));
135
136	CBS_init(&data, kData2, sizeof(kData2));
137	CHECK(!CBS_get_u16_length_prefixed(&data, &prefixed));
138
139	CBS_init(&data, kData3, sizeof(kData3));
140	CHECK(!CBS_get_u24_length_prefixed(&data, &prefixed));
141
142	return 1;
143}
144
145static int
146test_peek_u(void)
147{
148	static const uint8_t kData[] = {
149		1, 2, 3, 4, 5, 6, 7, 8, 9,
150	};
151	uint8_t u8;
152	uint16_t u16;
153	uint32_t u32;
154	CBS data;
155
156	CBS_init(&data, kData, sizeof(kData));
157
158	CHECK(CBS_peek_u8(&data, &u8));
159	CHECK(u8 == 1);
160	CHECK(CBS_peek_u16(&data, &u16));
161	CHECK(u16 == 0x102);
162	CHECK(CBS_peek_u24(&data, &u32));
163	CHECK(u32 == 0x10203);
164	CHECK(CBS_peek_u32(&data, &u32));
165	CHECK(u32 == 0x1020304);
166	CHECK(CBS_get_u32(&data, &u32));
167	CHECK(u32 == 0x1020304);
168	CHECK(CBS_peek_last_u8(&data, &u8));
169	CHECK(u8 == 9);
170	CHECK(CBS_peek_u32(&data, &u32));
171	CHECK(u32 == 0x5060708);
172	CHECK(CBS_get_u32(&data, &u32));
173	CHECK(u32 == 0x5060708);
174	CHECK(CBS_get_u8(&data, &u8));
175	CHECK(u8 == 9);
176	CHECK(!CBS_get_u8(&data, &u8));
177
178	return 1;
179}
180
181static int
182test_get_asn1(void)
183{
184	static const uint8_t kData1[] = {0x30, 2, 1, 2};
185	static const uint8_t kData2[] = {0x30, 3, 1, 2};
186	static const uint8_t kData3[] = {0x30, 0x80};
187	static const uint8_t kData4[] = {0x30, 0x81, 1, 1};
188	static const uint8_t kData5[4 + 0x80] = {0x30, 0x82, 0, 0x80};
189	static const uint8_t kData6[] = {0xa1, 3, 0x4, 1, 1};
190	static const uint8_t kData7[] = {0xa1, 3, 0x4, 2, 1};
191	static const uint8_t kData8[] = {0xa1, 3, 0x2, 1, 1};
192	static const uint8_t kData9[] = {0xa1, 3, 0x2, 1, 0xff};
193
194	CBS data, contents;
195	int present;
196	uint64_t value;
197
198	CBS_init(&data, kData1, sizeof(kData1));
199
200	CHECK(!CBS_peek_asn1_tag(&data, 0x1));
201	CHECK(CBS_peek_asn1_tag(&data, 0x30));
202
203	CHECK(CBS_get_asn1(&data, &contents, 0x30));
204	CHECK(CBS_len(&contents) == 2);
205	CHECK(memcmp(CBS_data(&contents), "\x01\x02", 2) == 0);
206
207	CBS_init(&data, kData2, sizeof(kData2));
208	/* data is truncated */
209	CHECK(!CBS_get_asn1(&data, &contents, 0x30));
210
211	CBS_init(&data, kData3, sizeof(kData3));
212	/* zero byte length of length */
213	CHECK(!CBS_get_asn1(&data, &contents, 0x30));
214
215	CBS_init(&data, kData4, sizeof(kData4));
216	/* long form mistakenly used. */
217	CHECK(!CBS_get_asn1(&data, &contents, 0x30));
218
219	CBS_init(&data, kData5, sizeof(kData5));
220	/* length takes too many bytes. */
221	CHECK(!CBS_get_asn1(&data, &contents, 0x30));
222
223	CBS_init(&data, kData1, sizeof(kData1));
224	/* wrong tag. */
225	CHECK(!CBS_get_asn1(&data, &contents, 0x31));
226
227	CBS_init(&data, NULL, 0);
228	/* peek at empty data. */
229	CHECK(!CBS_peek_asn1_tag(&data, 0x30));
230
231	CBS_init(&data, NULL, 0);
232	/* optional elements at empty data. */
233	CHECK(CBS_get_optional_asn1(&data, &contents, &present, 0xa0));
234	CHECK(!present);
235	CHECK(CBS_get_optional_asn1_octet_string(&data, &contents, &present,
236	    0xa0));
237	CHECK(!present);
238	CHECK(CBS_len(&contents) == 0);
239	CHECK(CBS_get_optional_asn1_octet_string(&data, &contents, NULL, 0xa0));
240	CHECK(CBS_len(&contents) == 0);
241	CHECK(CBS_get_optional_asn1_uint64(&data, &value, 0xa0, 42));
242	CHECK(value == 42);
243
244	CBS_init(&data, kData6, sizeof(kData6));
245	/* optional element. */
246	CHECK(CBS_get_optional_asn1(&data, &contents, &present, 0xa0));
247	CHECK(!present);
248	CHECK(CBS_get_optional_asn1(&data, &contents, &present, 0xa1));
249	CHECK(present);
250	CHECK(CBS_len(&contents) == 3);
251	CHECK(memcmp(CBS_data(&contents), "\x04\x01\x01", 3) == 0);
252
253	CBS_init(&data, kData6, sizeof(kData6));
254	/* optional octet string. */
255	CHECK(CBS_get_optional_asn1_octet_string(&data, &contents, &present,
256	    0xa0));
257	CHECK(!present);
258	CHECK(CBS_len(&contents) == 0);
259	CHECK(CBS_get_optional_asn1_octet_string(&data, &contents, &present,
260	    0xa1));
261	CHECK(present);
262	CHECK(CBS_len(&contents) == 1);
263	CHECK(CBS_data(&contents)[0] == 1);
264
265	CBS_init(&data, kData7, sizeof(kData7));
266	/* invalid optional octet string. */
267	CHECK(!CBS_get_optional_asn1_octet_string(&data, &contents, &present,
268	    0xa1));
269
270	CBS_init(&data, kData8, sizeof(kData8));
271	/* optional octet string. */
272	CHECK(CBS_get_optional_asn1_uint64(&data, &value, 0xa0, 42));
273	CHECK(value == 42);
274	CHECK(CBS_get_optional_asn1_uint64(&data, &value, 0xa1, 42));
275	CHECK(value == 1);
276
277	CBS_init(&data, kData9, sizeof(kData9));
278	/* invalid optional integer. */
279	CHECK(!CBS_get_optional_asn1_uint64(&data, &value, 0xa1, 42));
280
281	return 1;
282}
283
284static int
285test_get_optional_asn1_bool(void)
286{
287	CBS data;
288	int val;
289
290	static const uint8_t kTrue[] = {0x0a, 3, CBS_ASN1_BOOLEAN, 1, 0xff};
291	static const uint8_t kFalse[] = {0x0a, 3, CBS_ASN1_BOOLEAN, 1, 0x00};
292	static const uint8_t kInvalid[] = {0x0a, 3, CBS_ASN1_BOOLEAN, 1, 0x01};
293
294	CBS_init(&data, NULL, 0);
295	val = 2;
296	CHECK(CBS_get_optional_asn1_bool(&data, &val, 0x0a, 0));
297	CHECK(val == 0);
298
299	CBS_init(&data, kTrue, sizeof(kTrue));
300	val = 2;
301	CHECK(CBS_get_optional_asn1_bool(&data, &val, 0x0a, 0));
302	CHECK(val == 1);
303
304	CBS_init(&data, kFalse, sizeof(kFalse));
305	val = 2;
306	CHECK(CBS_get_optional_asn1_bool(&data, &val, 0x0a, 1));
307	CHECK(val == 0);
308
309	CBS_init(&data, kInvalid, sizeof(kInvalid));
310	CHECK(!CBS_get_optional_asn1_bool(&data, &val, 0x0a, 1));
311
312	return 1;
313}
314
315static int
316test_cbb_basic(void)
317{
318	static const uint8_t kExpected[] = {
319	    1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
320	    13, 14, 15, 16, 17, 18, 19, 20,
321	};
322	uint8_t *buf = NULL;
323	size_t buf_len;
324	int ret = 0;
325	CBB cbb;
326
327	CHECK(CBB_init(&cbb, 100));
328
329	CBB_cleanup(&cbb);
330
331	CHECK(CBB_init(&cbb, 0));
332	CHECK_GOTO(CBB_add_u8(&cbb, 1));
333	CHECK_GOTO(CBB_add_u16(&cbb, 0x203));
334	CHECK_GOTO(CBB_add_u24(&cbb, 0x40506));
335	CHECK_GOTO(CBB_add_u32(&cbb, 0x708090a));
336	CHECK_GOTO(CBB_add_bytes(&cbb, (const uint8_t*) "\x0b\x0c", 2));
337	CHECK_GOTO(CBB_add_u64(&cbb, 0xd0e0f1011121314LL));
338	CHECK_GOTO(CBB_finish(&cbb, &buf, &buf_len));
339
340	ret = (buf_len == sizeof(kExpected)
341	    && memcmp(buf, kExpected, buf_len) == 0);
342
343	if (0) {
344err:
345		CBB_cleanup(&cbb);
346	}
347	free(buf);
348	return ret;
349}
350
351static int
352test_cbb_add_space(void)
353{
354	static const uint8_t kExpected[] = {1, 2, 0, 0, 0, 0, 7, 8};
355	uint8_t *buf = NULL;
356	size_t buf_len;
357	uint8_t *data;
358	int ret = 0;
359	CBB cbb;
360
361	CHECK(CBB_init(&cbb, 100));
362
363	CHECK_GOTO(CBB_add_u16(&cbb, 0x102));
364	CHECK_GOTO(CBB_add_space(&cbb, &data, 4));
365	CHECK_GOTO(CBB_add_u16(&cbb, 0x708));
366	CHECK_GOTO(CBB_finish(&cbb, &buf, &buf_len));
367
368	ret |= (buf_len == sizeof(kExpected)
369	    && memcmp(buf, kExpected, buf_len) == 0);
370
371	memset(buf, 0xa5, buf_len);
372	CHECK(CBB_init_fixed(&cbb, buf, buf_len));
373
374	CHECK_GOTO(CBB_add_u16(&cbb, 0x102));
375	CHECK_GOTO(CBB_add_space(&cbb, &data, 4));
376	CHECK_GOTO(CBB_add_u16(&cbb, 0x708));
377	CHECK_GOTO(CBB_finish(&cbb, NULL, NULL));
378
379	ret |= (buf_len == sizeof(kExpected)
380	    && memcmp(buf, kExpected, buf_len) == 0);
381
382	if (0) {
383err:
384		CBB_cleanup(&cbb);
385	}
386	free(buf);
387	return ret;
388}
389
390static int
391test_cbb_fixed(void)
392{
393	CBB cbb;
394	uint8_t buf[1];
395	uint8_t *out_buf = NULL;
396	size_t out_size;
397	int ret = 0;
398
399	CHECK(CBB_init_fixed(&cbb, NULL, 0));
400	CHECK_GOTO(!CBB_add_u8(&cbb, 1));
401	CHECK_GOTO(CBB_finish(&cbb, &out_buf, &out_size));
402	CHECK(out_buf == NULL && out_size == 0);
403
404	CHECK(CBB_init_fixed(&cbb, buf, 1));
405	CHECK_GOTO(CBB_add_u8(&cbb, 1));
406	CHECK_GOTO(!CBB_add_u8(&cbb, 2));
407	CHECK_GOTO(CBB_finish(&cbb, &out_buf, &out_size));
408
409	ret = (out_buf == buf && out_size == 1 && buf[0] == 1);
410
411	if (0) {
412err:
413		CBB_cleanup(&cbb);
414	}
415
416	return ret;
417}
418
419static int
420test_cbb_finish_child(void)
421{
422	CBB cbb, child;
423	uint8_t *out_buf = NULL;
424	size_t out_size;
425	int ret = 0;
426
427	CHECK(CBB_init(&cbb, 16));
428	CHECK_GOTO(CBB_add_u8_length_prefixed(&cbb, &child));
429	CHECK_GOTO(!CBB_finish(&child, &out_buf, &out_size));
430	CHECK_GOTO(CBB_finish(&cbb, &out_buf, &out_size));
431
432	ret = (out_size == 1 && out_buf[0] == 0);
433
434err:
435	free(out_buf);
436	return ret;
437}
438
439static int
440test_cbb_prefixed(void)
441{
442	static const uint8_t kExpected[] = {0, 1, 1, 0, 2, 2, 3, 0, 0, 3,
443	    4, 5, 6, 5, 4, 1, 0, 1, 2};
444	CBB cbb, contents, inner_contents, inner_inner_contents;
445	uint8_t *buf = NULL;
446	size_t buf_len;
447	int ret = 0;
448
449	CHECK(CBB_init(&cbb, 0));
450	CHECK_GOTO(CBB_add_u8_length_prefixed(&cbb, &contents));
451	CHECK_GOTO(CBB_add_u8_length_prefixed(&cbb, &contents));
452	CHECK_GOTO(CBB_add_u8(&contents, 1));
453	CHECK_GOTO(CBB_add_u16_length_prefixed(&cbb, &contents));
454	CHECK_GOTO(CBB_add_u16(&contents, 0x203));
455	CHECK_GOTO(CBB_add_u24_length_prefixed(&cbb, &contents));
456	CHECK_GOTO(CBB_add_u24(&contents, 0x40506));
457	CHECK_GOTO(CBB_add_u8_length_prefixed(&cbb, &contents));
458	CHECK_GOTO(CBB_add_u8_length_prefixed(&contents, &inner_contents));
459	CHECK_GOTO(CBB_add_u8(&inner_contents, 1));
460	CHECK_GOTO(CBB_add_u16_length_prefixed(&inner_contents,
461	    &inner_inner_contents));
462	CHECK_GOTO(CBB_add_u8(&inner_inner_contents, 2));
463	CHECK_GOTO(CBB_finish(&cbb, &buf, &buf_len));
464
465	ret = (buf_len == sizeof(kExpected)
466	    && memcmp(buf, kExpected, buf_len) == 0);
467
468	if (0) {
469err:
470		CBB_cleanup(&cbb);
471	}
472	free(buf);
473	return ret;
474}
475
476static int
477test_cbb_discard_child(void)
478{
479	static const uint8_t kExpected[] = {
480		0xaa,
481		0,
482		1, 0xbb,
483		0, 2, 0xcc, 0xcc,
484		0, 0, 3, 0xdd, 0xdd, 0xdd,
485		1, 0xff,
486	};
487	CBB cbb, contents, inner_contents, inner_inner_contents;
488	uint8_t *buf = NULL;
489	size_t buf_len;
490	int ret = 0;
491
492	CHECK(CBB_init(&cbb, 0));
493	CHECK_GOTO(CBB_add_u8(&cbb, 0xaa));
494
495	// Discarding |cbb|'s children preserves the byte written.
496	CBB_discard_child(&cbb);
497
498	CHECK_GOTO(CBB_add_u8_length_prefixed(&cbb, &contents));
499	CHECK_GOTO(CBB_add_u8_length_prefixed(&cbb, &contents));
500	CHECK_GOTO(CBB_add_u8(&contents, 0xbb));
501	CHECK_GOTO(CBB_add_u16_length_prefixed(&cbb, &contents));
502	CHECK_GOTO(CBB_add_u16(&contents, 0xcccc));
503	CHECK_GOTO(CBB_add_u24_length_prefixed(&cbb, &contents));
504	CHECK_GOTO(CBB_add_u24(&contents, 0xdddddd));
505	CHECK_GOTO(CBB_add_u8_length_prefixed(&cbb, &contents));
506	CHECK_GOTO(CBB_add_u8(&contents, 0xff));
507	CHECK_GOTO(CBB_add_u8_length_prefixed(&contents, &inner_contents));
508	CHECK_GOTO(CBB_add_u8(&inner_contents, 0x42));
509	CHECK_GOTO(CBB_add_u16_length_prefixed(&inner_contents,
510	    &inner_inner_contents));
511	CHECK_GOTO(CBB_add_u8(&inner_inner_contents, 0x99));
512
513	// Discard everything from |inner_contents| down.
514	CBB_discard_child(&contents);
515
516	CHECK_GOTO(CBB_finish(&cbb, &buf, &buf_len));
517
518	ret = (buf_len == sizeof(kExpected)
519	    && memcmp(buf, kExpected, buf_len) == 0);
520
521	if (0) {
522err:
523		CBB_cleanup(&cbb);
524	}
525	free(buf);
526	return ret;
527}
528
529static int
530test_cbb_misuse(void)
531{
532	CBB cbb, child, contents;
533	uint8_t *buf = NULL;
534	size_t buf_len;
535	int ret = 0;
536
537	CHECK(CBB_init(&cbb, 0));
538	CHECK_GOTO(CBB_add_u8_length_prefixed(&cbb, &child));
539	CHECK_GOTO(CBB_add_u8(&child, 1));
540	CHECK_GOTO(CBB_add_u8(&cbb, 2));
541
542	/*
543	 * Since we wrote to |cbb|, |child| is now invalid and attempts to write
544	 * to it should fail.
545	 */
546	CHECK_GOTO(!CBB_add_u8(&child, 1));
547	CHECK_GOTO(!CBB_add_u16(&child, 1));
548	CHECK_GOTO(!CBB_add_u24(&child, 1));
549	CHECK_GOTO(!CBB_add_u8_length_prefixed(&child, &contents));
550	CHECK_GOTO(!CBB_add_u16_length_prefixed(&child, &contents));
551	CHECK_GOTO(!CBB_add_asn1(&child, &contents, 1));
552	CHECK_GOTO(!CBB_add_bytes(&child, (const uint8_t*) "a", 1));
553	CHECK_GOTO(CBB_finish(&cbb, &buf, &buf_len));
554
555	ret = (buf_len == 3 && memcmp(buf, "\x01\x01\x02", 3) == 0);
556
557	if (0) {
558err:
559		CBB_cleanup(&cbb);
560	}
561	free(buf);
562	return ret;
563}
564
565static int
566test_cbb_asn1(void)
567{
568	static const uint8_t kExpected[] = {0x30, 3, 1, 2, 3};
569	uint8_t *buf = NULL, *test_data = NULL;
570	size_t buf_len;
571	CBB cbb, contents, inner_contents;
572	int ret = 0;
573	int alloc = 0;
574
575	CHECK_GOTO(CBB_init(&cbb, 0));
576	alloc = 1;
577	CHECK_GOTO(CBB_add_asn1(&cbb, &contents, 0x30));
578	CHECK_GOTO(CBB_add_bytes(&contents, (const uint8_t*) "\x01\x02\x03",
579	    3));
580	CHECK_GOTO(CBB_finish(&cbb, &buf, &buf_len));
581	alloc = 0;
582
583	CHECK_GOTO(buf_len == sizeof(kExpected));
584	CHECK_GOTO(memcmp(buf, kExpected, buf_len) == 0);
585
586	free(buf);
587	buf = NULL;
588
589	CHECK_GOTO(((test_data = malloc(100000)) != NULL));
590	memset(test_data, 0x42, 100000);
591
592	CHECK_GOTO(CBB_init(&cbb, 0));
593	alloc = 1;
594	CHECK_GOTO(CBB_add_asn1(&cbb, &contents, 0x30));
595	CHECK_GOTO(CBB_add_bytes(&contents, test_data, 130));
596	CHECK_GOTO(CBB_finish(&cbb, &buf, &buf_len));
597	alloc = 0;
598
599	CHECK_GOTO(buf_len == 3 + 130);
600	CHECK_GOTO(memcmp(buf, "\x30\x81\x82", 3) == 0);
601	CHECK_GOTO(memcmp(buf + 3, test_data, 130) == 0);
602
603	free(buf);
604	buf = NULL;
605
606	CHECK_GOTO(CBB_init(&cbb, 0));
607	alloc = 1;
608	CHECK_GOTO(CBB_add_asn1(&cbb, &contents, 0x30));
609	CHECK_GOTO(CBB_add_bytes(&contents, test_data, 1000));
610	CHECK_GOTO(CBB_finish(&cbb, &buf, &buf_len));
611	alloc = 0;
612
613	CHECK_GOTO(buf_len == 4 + 1000);
614	CHECK_GOTO(memcmp(buf, "\x30\x82\x03\xe8", 4) == 0);
615	CHECK_GOTO(!memcmp(buf + 4, test_data, 1000));
616
617	free(buf);
618	buf = NULL;
619
620	CHECK_GOTO(CBB_init(&cbb, 0));
621	alloc = 1;
622	CHECK_GOTO(CBB_add_asn1(&cbb, &contents, 0x30));
623	CHECK_GOTO(CBB_add_asn1(&contents, &inner_contents, 0x30));
624	CHECK_GOTO(CBB_add_bytes(&inner_contents, test_data, 100000));
625	CHECK_GOTO(CBB_finish(&cbb, &buf, &buf_len));
626	alloc = 0;
627
628	CHECK_GOTO(buf_len == 5 + 5 + 100000);
629	CHECK_GOTO(memcmp(buf, "\x30\x83\x01\x86\xa5\x30\x83\x01\x86\xa0", 10)
630	    == 0);
631	CHECK_GOTO(!memcmp(buf + 10, test_data, 100000));
632
633	ret = 1;
634
635	if (0) {
636err:
637		if (alloc)
638			CBB_cleanup(&cbb);
639	}
640	free(buf);
641	free(test_data);
642	return ret;
643}
644
645static int
646do_indefinite_convert(const char *name, const uint8_t *definite_expected,
647    size_t definite_len, const uint8_t *indefinite, size_t indefinite_len)
648{
649	CBS in;
650	uint8_t *out = NULL;
651	size_t out_len;
652	int ret = 0;
653
654	CBS_init(&in, indefinite, indefinite_len);
655
656	CHECK_GOTO(CBS_asn1_indefinite_to_definite(&in, &out, &out_len));
657
658	if (out == NULL) {
659
660		if (indefinite_len != definite_len ||
661		    memcmp(definite_expected, indefinite, indefinite_len) != 0) {
662			PRINT_ERROR;
663			goto err;
664		}
665
666		return 1;
667	}
668
669	if (out_len != definite_len ||
670	    memcmp(out, definite_expected, definite_len) != 0) {
671		PRINT_ERROR;
672		goto err;
673	}
674
675	ret = 1;
676err:
677	free(out);
678	return ret;
679}
680
681static int
682test_indefinite_convert(void)
683{
684	static const uint8_t kSimpleBER[] = {0x01, 0x01, 0x00};
685
686	/* kIndefBER contains a SEQUENCE with an indefinite length. */
687	static const uint8_t kIndefBER[] = {0x30, 0x80, 0x01, 0x01, 0x02, 0x00,
688	    0x00};
689	static const uint8_t kIndefDER[] = {0x30, 0x03, 0x01, 0x01, 0x02};
690
691	/*
692	 * kOctetStringBER contains an indefinite length OCTETSTRING with two
693	 * parts.  These parts need to be concatenated in DER form.
694	 */
695	static const uint8_t kOctetStringBER[] = {0x24, 0x80, 0x04, 0x02, 0,
696	    1, 0x04, 0x02, 2,    3,    0x00, 0x00};
697	static const uint8_t kOctetStringDER[] = {0x04, 0x04, 0, 1, 2, 3};
698
699	/*
700	 * kNSSBER is part of a PKCS#12 message generated by NSS that uses
701	 * indefinite length elements extensively.
702	 */
703	static const uint8_t kNSSBER[] = {
704	    0x30, 0x80, 0x02, 0x01, 0x03, 0x30, 0x80, 0x06, 0x09, 0x2a, 0x86,
705	    0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x80, 0x24, 0x80,
706	    0x04, 0x04, 0x01, 0x02, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
707	    0x00, 0x30, 0x39, 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e,
708	    0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14, 0x84, 0x98, 0xfc, 0x66,
709	    0x33, 0xee, 0xba, 0xe7, 0x90, 0xc1, 0xb6, 0xe8, 0x8f, 0xfe, 0x1d,
710	    0xc5, 0xa5, 0x97, 0x93, 0x3e, 0x04, 0x10, 0x38, 0x62, 0xc6, 0x44,
711	    0x12, 0xd5, 0x30, 0x00, 0xf8, 0xf2, 0x1b, 0xf0, 0x6e, 0x10, 0x9b,
712	    0xb8, 0x02, 0x02, 0x07, 0xd0, 0x00, 0x00,
713	};
714
715	static const uint8_t kNSSDER[] = {
716	    0x30, 0x53, 0x02, 0x01, 0x03, 0x30, 0x13, 0x06, 0x09, 0x2a, 0x86,
717	    0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x06, 0x04, 0x04,
718	    0x01, 0x02, 0x03, 0x04, 0x30, 0x39, 0x30, 0x21, 0x30, 0x09, 0x06,
719	    0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14, 0x84,
720	    0x98, 0xfc, 0x66, 0x33, 0xee, 0xba, 0xe7, 0x90, 0xc1, 0xb6, 0xe8,
721	    0x8f, 0xfe, 0x1d, 0xc5, 0xa5, 0x97, 0x93, 0x3e, 0x04, 0x10, 0x38,
722	    0x62, 0xc6, 0x44, 0x12, 0xd5, 0x30, 0x00, 0xf8, 0xf2, 0x1b, 0xf0,
723	    0x6e, 0x10, 0x9b, 0xb8, 0x02, 0x02, 0x07, 0xd0,
724	};
725
726	CHECK(do_indefinite_convert("kSimpleBER", kSimpleBER, sizeof(kSimpleBER),
727	    kSimpleBER, sizeof(kSimpleBER)));
728	CHECK(do_indefinite_convert("kIndefBER", kIndefDER, sizeof(kIndefDER),
729	    kIndefBER, sizeof(kIndefBER)));
730	CHECK(do_indefinite_convert("kOctetStringBER", kOctetStringDER,
731	    sizeof(kOctetStringDER), kOctetStringBER,
732	    sizeof(kOctetStringBER)));
733	CHECK(do_indefinite_convert("kNSSBER", kNSSDER, sizeof(kNSSDER), kNSSBER,
734	    sizeof(kNSSBER)));
735
736	return 1;
737}
738
739typedef struct {
740	uint64_t value;
741	const char *encoding;
742	size_t encoding_len;
743} ASN1_UINT64_TEST;
744
745static const ASN1_UINT64_TEST kAsn1Uint64Tests[] = {
746	{0, "\x02\x01\x00", 3},
747	{1, "\x02\x01\x01", 3},
748	{127, "\x02\x01\x7f", 3},
749	{128, "\x02\x02\x00\x80", 4},
750	{0xdeadbeef, "\x02\x05\x00\xde\xad\xbe\xef", 7},
751	{OPENSSL_U64(0x0102030405060708),
752	    "\x02\x08\x01\x02\x03\x04\x05\x06\x07\x08", 10},
753	{OPENSSL_U64(0xffffffffffffffff),
754	    "\x02\x09\x00\xff\xff\xff\xff\xff\xff\xff\xff", 11},
755};
756
757typedef struct {
758	const char *encoding;
759	size_t encoding_len;
760} ASN1_INVALID_UINT64_TEST;
761
762static const ASN1_INVALID_UINT64_TEST kAsn1InvalidUint64Tests[] = {
763	/* Bad tag. */
764	{"\x03\x01\x00", 3},
765	/* Empty contents. */
766	{"\x02\x00", 2},
767	/* Negative number. */
768	{"\x02\x01\x80", 3},
769	/* Overflow. */
770	{"\x02\x09\x01\x00\x00\x00\x00\x00\x00\x00\x00", 11},
771	/* Leading zeros. */
772	{"\x02\x02\x00\x01", 4},
773};
774
775static int
776test_asn1_uint64(void)
777{
778	CBB cbb;
779	uint8_t *out = NULL;
780	size_t i;
781	int ret = 0;
782	int alloc = 0;
783
784	for (i = 0; i < sizeof(kAsn1Uint64Tests) / sizeof(kAsn1Uint64Tests[0]);
785	     i++) {
786		const ASN1_UINT64_TEST *test = &kAsn1Uint64Tests[i];
787		CBS cbs;
788		uint64_t value;
789		size_t len;
790
791		CBS_init(&cbs, (const uint8_t *)test->encoding,
792		    test->encoding_len);
793
794		CHECK(CBS_get_asn1_uint64(&cbs, &value));
795		CHECK(CBS_len(&cbs) == 0);
796		CHECK(value == test->value);
797
798		CHECK(CBB_init(&cbb, 0));
799		alloc = 1;
800		CHECK_GOTO(CBB_add_asn1_uint64(&cbb, test->value));
801		CHECK_GOTO(CBB_finish(&cbb, &out, &len));
802		alloc = 0;
803
804		CHECK_GOTO(len == test->encoding_len);
805		CHECK_GOTO(memcmp(out, test->encoding, len) == 0);
806		free(out);
807		out = NULL;
808	}
809
810	for (i = 0; i < sizeof(kAsn1InvalidUint64Tests)
811	    / sizeof(kAsn1InvalidUint64Tests[0]); i++) {
812		const ASN1_INVALID_UINT64_TEST *test =
813		    &kAsn1InvalidUint64Tests[i];
814		CBS cbs;
815		uint64_t value;
816
817		CBS_init(&cbs, (const uint8_t *)test->encoding,
818		    test->encoding_len);
819		CHECK(!CBS_get_asn1_uint64(&cbs, &value));
820	}
821
822	ret = 1;
823
824	if (0) {
825err:
826		if (alloc)
827			CBB_cleanup(&cbb);
828	}
829	free(out);
830
831	return ret;
832}
833
834static int
835test_offset(void)
836{
837	uint8_t v;
838	static const uint8_t input[] = {1, 2, 3, 4, 5};
839	CBS data;
840
841	CBS_init(&data, input, sizeof(input));
842	CHECK(sizeof(input) == 5);
843	CHECK(CBS_len(&data) == 5);
844	CHECK(CBS_offset(&data) == 0);
845	CHECK(CBS_get_u8(&data, &v));
846	CHECK(v == 1);
847	CHECK(CBS_len(&data) == 4);
848	CHECK(CBS_offset(&data) == 1);
849	CHECK(CBS_skip(&data, 2));
850	CHECK(CBS_len(&data) == 2);
851	CHECK(CBS_offset(&data) == 3);
852	CHECK(CBS_get_u8(&data, &v));
853	CHECK(v == 4);
854	CHECK(CBS_get_u8(&data, &v));
855	CHECK(v == 5);
856	CHECK(CBS_len(&data) == 0);
857	CHECK(CBS_offset(&data) == 5);
858	CHECK(!CBS_skip(&data, 1));
859
860	CBS_init(&data, input, sizeof(input));
861	CHECK(CBS_skip(&data, 2));
862	CHECK(CBS_len(&data) == 3);
863	CHECK(CBS_offset(&data) == 2);
864	CHECK(CBS_skip(&data, 3));
865	CHECK(CBS_len(&data) == 0);
866	CHECK(CBS_offset(&data) == 5);
867	CHECK(!CBS_get_u8(&data, &v));
868
869	return 1;
870}
871
872static int
873test_write_bytes(void)
874{
875	int ret = 0;
876	uint8_t v;
877	size_t len;
878	static const uint8_t input[] = {'f', 'o', 'o', 'b', 'a', 'r'};
879	CBS data;
880	uint8_t *tmp = NULL;
881
882	CHECK_GOTO((tmp = malloc(sizeof(input))) != NULL);
883	memset(tmp, 100, sizeof(input));
884
885	CBS_init(&data, input, sizeof(input));
886	CHECK_GOTO(CBS_len(&data) == 6);
887	CHECK_GOTO(CBS_offset(&data) == 0);
888	CHECK_GOTO(CBS_get_u8(&data, &v));
889	CHECK_GOTO(v == 102 /* f */);
890	CHECK_GOTO(CBS_skip(&data, 1));
891	CHECK_GOTO(!CBS_skip(&data, 15));
892	CHECK_GOTO(CBS_write_bytes(&data, tmp, sizeof(input), &len));
893	CHECK_GOTO(len == 4);
894	CHECK_GOTO(memcmp(input + 2, tmp, len) == 0);
895	CHECK_GOTO(tmp[4] == 100 && tmp[5] == 100);
896
897	ret = 1;
898
899err:
900	free(tmp);
901	return ret;
902}
903
904static int
905test_cbs_dup(void)
906{
907	CBS data, check;
908	static const uint8_t input[] = {'f', 'o', 'o', 'b', 'a', 'r'};
909
910	CBS_init(&data, input, sizeof(input));
911	CHECK(CBS_len(&data) == 6);
912	CBS_dup(&data, &check);
913	CHECK(CBS_len(&check) == 6);
914	CHECK(CBS_data(&data) == CBS_data(&check));
915	CHECK(CBS_skip(&data, 1));
916	CHECK(CBS_len(&data) == 5);
917	CHECK(CBS_len(&check) == 6);
918	CHECK(CBS_data(&data) == CBS_data(&check) + 1);
919	CHECK(CBS_skip(&check, 1));
920	CHECK(CBS_len(&data) == 5);
921	CHECK(CBS_len(&check) == 5);
922	CHECK(CBS_data(&data) == CBS_data(&check));
923	CHECK(CBS_offset(&data) == 1);
924	CHECK(CBS_offset(&check) == 1);
925
926	CBS_init(&data, input, sizeof(input));
927	CHECK(CBS_skip(&data, 5));
928	CBS_dup(&data, &check);
929	CHECK(CBS_len(&data) == 1);
930	CHECK(CBS_len(&check) == 1);
931	CHECK(CBS_data(&data) == input + 5);
932	CHECK(CBS_data(&data) == CBS_data(&check));
933	CHECK(CBS_offset(&data) == 5);
934	CHECK(CBS_offset(&check) == 5);
935
936	return 1;
937}
938
939int
940main(void)
941{
942	int failed = 0;
943
944	failed |= !test_skip();
945	failed |= !test_get_u();
946	failed |= !test_get_prefixed();
947	failed |= !test_get_prefixed_bad();
948	failed |= !test_peek_u();
949	failed |= !test_get_asn1();
950	failed |= !test_cbb_basic();
951	failed |= !test_cbb_add_space();
952	failed |= !test_cbb_fixed();
953	failed |= !test_cbb_finish_child();
954	failed |= !test_cbb_discard_child();
955	failed |= !test_cbb_misuse();
956	failed |= !test_cbb_prefixed();
957	failed |= !test_cbb_asn1();
958	failed |= !test_indefinite_convert();
959	failed |= !test_asn1_uint64();
960	failed |= !test_get_optional_asn1_bool();
961	failed |= !test_offset();
962	failed |= !test_write_bytes();
963	failed |= !test_cbs_dup();
964
965	if (!failed)
966		printf("PASS\n");
967	return failed;
968}
969