bytestringtest.c revision 1.15
1/*	$OpenBSD: bytestringtest.c,v 1.15 2021/12/15 17:37:42 jsing 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 == 0x0b0c0d0e0f101112U);
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[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
319	uint8_t *buf = NULL;
320	size_t buf_len;
321	int ret = 0;
322	CBB cbb;
323
324	CHECK(CBB_init(&cbb, 100));
325
326	CBB_cleanup(&cbb);
327
328	CHECK(CBB_init(&cbb, 0));
329	CHECK_GOTO(CBB_add_u8(&cbb, 1));
330	CHECK_GOTO(CBB_add_u16(&cbb, 0x203));
331	CHECK_GOTO(CBB_add_u24(&cbb, 0x40506));
332	CHECK_GOTO(CBB_add_u32(&cbb, 0x708090a));
333	CHECK_GOTO(CBB_add_bytes(&cbb, (const uint8_t*) "\x0b\x0c", 2));
334	CHECK_GOTO(CBB_finish(&cbb, &buf, &buf_len));
335
336	ret = (buf_len == sizeof(kExpected)
337	    && memcmp(buf, kExpected, buf_len) == 0);
338
339	if (0) {
340err:
341		CBB_cleanup(&cbb);
342	}
343	free(buf);
344	return ret;
345}
346
347static int
348test_cbb_add_space(void)
349{
350	static const uint8_t kExpected[] = {1, 2, 0, 0, 0, 0, 7, 8};
351	uint8_t *buf = NULL;
352	size_t buf_len;
353	uint8_t *data;
354	int ret = 0;
355	CBB cbb;
356
357	CHECK(CBB_init(&cbb, 100));
358
359	CHECK_GOTO(CBB_add_u16(&cbb, 0x102));
360	CHECK_GOTO(CBB_add_space(&cbb, &data, 4));
361	CHECK_GOTO(CBB_add_u16(&cbb, 0x708));
362	CHECK_GOTO(CBB_finish(&cbb, &buf, &buf_len));
363
364	ret |= (buf_len == sizeof(kExpected)
365	    && memcmp(buf, kExpected, buf_len) == 0);
366
367	memset(buf, 0xa5, buf_len);
368	CHECK(CBB_init_fixed(&cbb, buf, buf_len));
369
370	CHECK_GOTO(CBB_add_u16(&cbb, 0x102));
371	CHECK_GOTO(CBB_add_space(&cbb, &data, 4));
372	CHECK_GOTO(CBB_add_u16(&cbb, 0x708));
373	CHECK_GOTO(CBB_finish(&cbb, NULL, NULL));
374
375	ret |= (buf_len == sizeof(kExpected)
376	    && memcmp(buf, kExpected, buf_len) == 0);
377
378	if (0) {
379err:
380		CBB_cleanup(&cbb);
381	}
382	free(buf);
383	return ret;
384}
385
386static int
387test_cbb_fixed(void)
388{
389	CBB cbb;
390	uint8_t buf[1];
391	uint8_t *out_buf = NULL;
392	size_t out_size;
393	int ret = 0;
394
395	CHECK(CBB_init_fixed(&cbb, NULL, 0));
396	CHECK_GOTO(!CBB_add_u8(&cbb, 1));
397	CHECK_GOTO(CBB_finish(&cbb, &out_buf, &out_size));
398	CHECK(out_buf == NULL && out_size == 0);
399
400	CHECK(CBB_init_fixed(&cbb, buf, 1));
401	CHECK_GOTO(CBB_add_u8(&cbb, 1));
402	CHECK_GOTO(!CBB_add_u8(&cbb, 2));
403	CHECK_GOTO(CBB_finish(&cbb, &out_buf, &out_size));
404
405	ret = (out_buf == buf && out_size == 1 && buf[0] == 1);
406
407	if (0) {
408err:
409		CBB_cleanup(&cbb);
410	}
411
412	return ret;
413}
414
415static int
416test_cbb_finish_child(void)
417{
418	CBB cbb, child;
419	uint8_t *out_buf = NULL;
420	size_t out_size;
421	int ret = 0;
422
423	CHECK(CBB_init(&cbb, 16));
424	CHECK_GOTO(CBB_add_u8_length_prefixed(&cbb, &child));
425	CHECK_GOTO(!CBB_finish(&child, &out_buf, &out_size));
426	CHECK_GOTO(CBB_finish(&cbb, &out_buf, &out_size));
427
428	ret = (out_size == 1 && out_buf[0] == 0);
429
430err:
431	free(out_buf);
432	return ret;
433}
434
435static int
436test_cbb_prefixed(void)
437{
438	static const uint8_t kExpected[] = {0, 1, 1, 0, 2, 2, 3, 0, 0, 3,
439	    4, 5, 6, 5, 4, 1, 0, 1, 2};
440	CBB cbb, contents, inner_contents, inner_inner_contents;
441	uint8_t *buf = NULL;
442	size_t buf_len;
443	int ret = 0;
444
445	CHECK(CBB_init(&cbb, 0));
446	CHECK_GOTO(CBB_add_u8_length_prefixed(&cbb, &contents));
447	CHECK_GOTO(CBB_add_u8_length_prefixed(&cbb, &contents));
448	CHECK_GOTO(CBB_add_u8(&contents, 1));
449	CHECK_GOTO(CBB_add_u16_length_prefixed(&cbb, &contents));
450	CHECK_GOTO(CBB_add_u16(&contents, 0x203));
451	CHECK_GOTO(CBB_add_u24_length_prefixed(&cbb, &contents));
452	CHECK_GOTO(CBB_add_u24(&contents, 0x40506));
453	CHECK_GOTO(CBB_add_u8_length_prefixed(&cbb, &contents));
454	CHECK_GOTO(CBB_add_u8_length_prefixed(&contents, &inner_contents));
455	CHECK_GOTO(CBB_add_u8(&inner_contents, 1));
456	CHECK_GOTO(CBB_add_u16_length_prefixed(&inner_contents,
457	    &inner_inner_contents));
458	CHECK_GOTO(CBB_add_u8(&inner_inner_contents, 2));
459	CHECK_GOTO(CBB_finish(&cbb, &buf, &buf_len));
460
461	ret = (buf_len == sizeof(kExpected)
462	    && memcmp(buf, kExpected, buf_len) == 0);
463
464	if (0) {
465err:
466		CBB_cleanup(&cbb);
467	}
468	free(buf);
469	return ret;
470}
471
472static int
473test_cbb_discard_child(void)
474{
475	static const uint8_t kExpected[] = {
476		0xaa,
477		0,
478		1, 0xbb,
479		0, 2, 0xcc, 0xcc,
480		0, 0, 3, 0xdd, 0xdd, 0xdd,
481		1, 0xff,
482	};
483	CBB cbb, contents, inner_contents, inner_inner_contents;
484	uint8_t *buf = NULL;
485	size_t buf_len;
486	int ret = 0;
487
488	CHECK(CBB_init(&cbb, 0));
489	CHECK_GOTO(CBB_add_u8(&cbb, 0xaa));
490
491	// Discarding |cbb|'s children preserves the byte written.
492	CBB_discard_child(&cbb);
493
494	CHECK_GOTO(CBB_add_u8_length_prefixed(&cbb, &contents));
495	CHECK_GOTO(CBB_add_u8_length_prefixed(&cbb, &contents));
496	CHECK_GOTO(CBB_add_u8(&contents, 0xbb));
497	CHECK_GOTO(CBB_add_u16_length_prefixed(&cbb, &contents));
498	CHECK_GOTO(CBB_add_u16(&contents, 0xcccc));
499	CHECK_GOTO(CBB_add_u24_length_prefixed(&cbb, &contents));
500	CHECK_GOTO(CBB_add_u24(&contents, 0xdddddd));
501	CHECK_GOTO(CBB_add_u8_length_prefixed(&cbb, &contents));
502	CHECK_GOTO(CBB_add_u8(&contents, 0xff));
503	CHECK_GOTO(CBB_add_u8_length_prefixed(&contents, &inner_contents));
504	CHECK_GOTO(CBB_add_u8(&inner_contents, 0x42));
505	CHECK_GOTO(CBB_add_u16_length_prefixed(&inner_contents,
506	    &inner_inner_contents));
507	CHECK_GOTO(CBB_add_u8(&inner_inner_contents, 0x99));
508
509	// Discard everything from |inner_contents| down.
510	CBB_discard_child(&contents);
511
512	CHECK_GOTO(CBB_finish(&cbb, &buf, &buf_len));
513
514	ret = (buf_len == sizeof(kExpected)
515	    && memcmp(buf, kExpected, buf_len) == 0);
516
517	if (0) {
518err:
519		CBB_cleanup(&cbb);
520	}
521	free(buf);
522	return ret;
523}
524
525static int
526test_cbb_misuse(void)
527{
528	CBB cbb, child, contents;
529	uint8_t *buf = NULL;
530	size_t buf_len;
531	int ret = 0;
532
533	CHECK(CBB_init(&cbb, 0));
534	CHECK_GOTO(CBB_add_u8_length_prefixed(&cbb, &child));
535	CHECK_GOTO(CBB_add_u8(&child, 1));
536	CHECK_GOTO(CBB_add_u8(&cbb, 2));
537
538	/*
539	 * Since we wrote to |cbb|, |child| is now invalid and attempts to write
540	 * to it should fail.
541	 */
542	CHECK_GOTO(!CBB_add_u8(&child, 1));
543	CHECK_GOTO(!CBB_add_u16(&child, 1));
544	CHECK_GOTO(!CBB_add_u24(&child, 1));
545	CHECK_GOTO(!CBB_add_u8_length_prefixed(&child, &contents));
546	CHECK_GOTO(!CBB_add_u16_length_prefixed(&child, &contents));
547	CHECK_GOTO(!CBB_add_asn1(&child, &contents, 1));
548	CHECK_GOTO(!CBB_add_bytes(&child, (const uint8_t*) "a", 1));
549	CHECK_GOTO(CBB_finish(&cbb, &buf, &buf_len));
550
551	ret = (buf_len == 3 && memcmp(buf, "\x01\x01\x02", 3) == 0);
552
553	if (0) {
554err:
555		CBB_cleanup(&cbb);
556	}
557	free(buf);
558	return ret;
559}
560
561static int
562test_cbb_asn1(void)
563{
564	static const uint8_t kExpected[] = {0x30, 3, 1, 2, 3};
565	uint8_t *buf = NULL, *test_data = NULL;
566	size_t buf_len;
567	CBB cbb, contents, inner_contents;
568	int ret = 0;
569	int alloc = 0;
570
571	CHECK_GOTO(CBB_init(&cbb, 0));
572	alloc = 1;
573	CHECK_GOTO(CBB_add_asn1(&cbb, &contents, 0x30));
574	CHECK_GOTO(CBB_add_bytes(&contents, (const uint8_t*) "\x01\x02\x03",
575	    3));
576	CHECK_GOTO(CBB_finish(&cbb, &buf, &buf_len));
577	alloc = 0;
578
579	CHECK_GOTO(buf_len == sizeof(kExpected));
580	CHECK_GOTO(memcmp(buf, kExpected, buf_len) == 0);
581
582	free(buf);
583	buf = NULL;
584
585	CHECK_GOTO(((test_data = malloc(100000)) != NULL));
586	memset(test_data, 0x42, 100000);
587
588	CHECK_GOTO(CBB_init(&cbb, 0));
589	alloc = 1;
590	CHECK_GOTO(CBB_add_asn1(&cbb, &contents, 0x30));
591	CHECK_GOTO(CBB_add_bytes(&contents, test_data, 130));
592	CHECK_GOTO(CBB_finish(&cbb, &buf, &buf_len));
593	alloc = 0;
594
595	CHECK_GOTO(buf_len == 3 + 130);
596	CHECK_GOTO(memcmp(buf, "\x30\x81\x82", 3) == 0);
597	CHECK_GOTO(memcmp(buf + 3, test_data, 130) == 0);
598
599	free(buf);
600	buf = NULL;
601
602	CHECK_GOTO(CBB_init(&cbb, 0));
603	alloc = 1;
604	CHECK_GOTO(CBB_add_asn1(&cbb, &contents, 0x30));
605	CHECK_GOTO(CBB_add_bytes(&contents, test_data, 1000));
606	CHECK_GOTO(CBB_finish(&cbb, &buf, &buf_len));
607	alloc = 0;
608
609	CHECK_GOTO(buf_len == 4 + 1000);
610	CHECK_GOTO(memcmp(buf, "\x30\x82\x03\xe8", 4) == 0);
611	CHECK_GOTO(!memcmp(buf + 4, test_data, 1000));
612
613	free(buf);
614	buf = NULL;
615
616	CHECK_GOTO(CBB_init(&cbb, 0));
617	alloc = 1;
618	CHECK_GOTO(CBB_add_asn1(&cbb, &contents, 0x30));
619	CHECK_GOTO(CBB_add_asn1(&contents, &inner_contents, 0x30));
620	CHECK_GOTO(CBB_add_bytes(&inner_contents, test_data, 100000));
621	CHECK_GOTO(CBB_finish(&cbb, &buf, &buf_len));
622	alloc = 0;
623
624	CHECK_GOTO(buf_len == 5 + 5 + 100000);
625	CHECK_GOTO(memcmp(buf, "\x30\x83\x01\x86\xa5\x30\x83\x01\x86\xa0", 10)
626	    == 0);
627	CHECK_GOTO(!memcmp(buf + 10, test_data, 100000));
628
629	ret = 1;
630
631	if (0) {
632err:
633		if (alloc)
634			CBB_cleanup(&cbb);
635	}
636	free(buf);
637	free(test_data);
638	return ret;
639}
640
641static int
642do_indefinite_convert(const char *name, const uint8_t *definite_expected,
643    size_t definite_len, const uint8_t *indefinite, size_t indefinite_len)
644{
645	CBS in;
646	uint8_t *out = NULL;
647	size_t out_len;
648	int ret = 0;
649
650	CBS_init(&in, indefinite, indefinite_len);
651
652	CHECK_GOTO(CBS_asn1_indefinite_to_definite(&in, &out, &out_len));
653
654	if (out == NULL) {
655
656		if (indefinite_len != definite_len ||
657		    memcmp(definite_expected, indefinite, indefinite_len) != 0) {
658			PRINT_ERROR;
659			goto err;
660		}
661
662		return 1;
663	}
664
665	if (out_len != definite_len ||
666	    memcmp(out, definite_expected, definite_len) != 0) {
667		PRINT_ERROR;
668		goto err;
669	}
670
671	ret = 1;
672err:
673	free(out);
674	return ret;
675}
676
677static int
678test_indefinite_convert(void)
679{
680	static const uint8_t kSimpleBER[] = {0x01, 0x01, 0x00};
681
682	/* kIndefBER contains a SEQUENCE with an indefinite length. */
683	static const uint8_t kIndefBER[] = {0x30, 0x80, 0x01, 0x01, 0x02, 0x00,
684	    0x00};
685	static const uint8_t kIndefDER[] = {0x30, 0x03, 0x01, 0x01, 0x02};
686
687	/*
688	 * kOctetStringBER contains an indefinite length OCTETSTRING with two
689	 * parts.  These parts need to be concatenated in DER form.
690	 */
691	static const uint8_t kOctetStringBER[] = {0x24, 0x80, 0x04, 0x02, 0,
692	    1, 0x04, 0x02, 2,    3,    0x00, 0x00};
693	static const uint8_t kOctetStringDER[] = {0x04, 0x04, 0, 1, 2, 3};
694
695	/*
696	 * kNSSBER is part of a PKCS#12 message generated by NSS that uses
697	 * indefinite length elements extensively.
698	 */
699	static const uint8_t kNSSBER[] = {
700	    0x30, 0x80, 0x02, 0x01, 0x03, 0x30, 0x80, 0x06, 0x09, 0x2a, 0x86,
701	    0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x80, 0x24, 0x80,
702	    0x04, 0x04, 0x01, 0x02, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
703	    0x00, 0x30, 0x39, 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e,
704	    0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14, 0x84, 0x98, 0xfc, 0x66,
705	    0x33, 0xee, 0xba, 0xe7, 0x90, 0xc1, 0xb6, 0xe8, 0x8f, 0xfe, 0x1d,
706	    0xc5, 0xa5, 0x97, 0x93, 0x3e, 0x04, 0x10, 0x38, 0x62, 0xc6, 0x44,
707	    0x12, 0xd5, 0x30, 0x00, 0xf8, 0xf2, 0x1b, 0xf0, 0x6e, 0x10, 0x9b,
708	    0xb8, 0x02, 0x02, 0x07, 0xd0, 0x00, 0x00,
709	};
710
711	static const uint8_t kNSSDER[] = {
712	    0x30, 0x53, 0x02, 0x01, 0x03, 0x30, 0x13, 0x06, 0x09, 0x2a, 0x86,
713	    0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x06, 0x04, 0x04,
714	    0x01, 0x02, 0x03, 0x04, 0x30, 0x39, 0x30, 0x21, 0x30, 0x09, 0x06,
715	    0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14, 0x84,
716	    0x98, 0xfc, 0x66, 0x33, 0xee, 0xba, 0xe7, 0x90, 0xc1, 0xb6, 0xe8,
717	    0x8f, 0xfe, 0x1d, 0xc5, 0xa5, 0x97, 0x93, 0x3e, 0x04, 0x10, 0x38,
718	    0x62, 0xc6, 0x44, 0x12, 0xd5, 0x30, 0x00, 0xf8, 0xf2, 0x1b, 0xf0,
719	    0x6e, 0x10, 0x9b, 0xb8, 0x02, 0x02, 0x07, 0xd0,
720	};
721
722	CHECK(do_indefinite_convert("kSimpleBER", kSimpleBER, sizeof(kSimpleBER),
723	    kSimpleBER, sizeof(kSimpleBER)));
724	CHECK(do_indefinite_convert("kIndefBER", kIndefDER, sizeof(kIndefDER),
725	    kIndefBER, sizeof(kIndefBER)));
726	CHECK(do_indefinite_convert("kOctetStringBER", kOctetStringDER,
727	    sizeof(kOctetStringDER), kOctetStringBER,
728	    sizeof(kOctetStringBER)));
729	CHECK(do_indefinite_convert("kNSSBER", kNSSDER, sizeof(kNSSDER), kNSSBER,
730	    sizeof(kNSSBER)));
731
732	return 1;
733}
734
735typedef struct {
736	uint64_t value;
737	const char *encoding;
738	size_t encoding_len;
739} ASN1_UINT64_TEST;
740
741static const ASN1_UINT64_TEST kAsn1Uint64Tests[] = {
742	{0, "\x02\x01\x00", 3},
743	{1, "\x02\x01\x01", 3},
744	{127, "\x02\x01\x7f", 3},
745	{128, "\x02\x02\x00\x80", 4},
746	{0xdeadbeef, "\x02\x05\x00\xde\xad\xbe\xef", 7},
747	{OPENSSL_U64(0x0102030405060708),
748	    "\x02\x08\x01\x02\x03\x04\x05\x06\x07\x08", 10},
749	{OPENSSL_U64(0xffffffffffffffff),
750	    "\x02\x09\x00\xff\xff\xff\xff\xff\xff\xff\xff", 11},
751};
752
753typedef struct {
754	const char *encoding;
755	size_t encoding_len;
756} ASN1_INVALID_UINT64_TEST;
757
758static const ASN1_INVALID_UINT64_TEST kAsn1InvalidUint64Tests[] = {
759	/* Bad tag. */
760	{"\x03\x01\x00", 3},
761	/* Empty contents. */
762	{"\x02\x00", 2},
763	/* Negative number. */
764	{"\x02\x01\x80", 3},
765	/* Overflow. */
766	{"\x02\x09\x01\x00\x00\x00\x00\x00\x00\x00\x00", 11},
767	/* Leading zeros. */
768	{"\x02\x02\x00\x01", 4},
769};
770
771static int
772test_asn1_uint64(void)
773{
774	CBB cbb;
775	uint8_t *out = NULL;
776	size_t i;
777	int ret = 0;
778	int alloc = 0;
779
780	for (i = 0; i < sizeof(kAsn1Uint64Tests) / sizeof(kAsn1Uint64Tests[0]);
781	     i++) {
782		const ASN1_UINT64_TEST *test = &kAsn1Uint64Tests[i];
783		CBS cbs;
784		uint64_t value;
785		size_t len;
786
787		CBS_init(&cbs, (const uint8_t *)test->encoding,
788		    test->encoding_len);
789
790		CHECK(CBS_get_asn1_uint64(&cbs, &value));
791		CHECK(CBS_len(&cbs) == 0);
792		CHECK(value == test->value);
793
794		CHECK(CBB_init(&cbb, 0));
795		alloc = 1;
796		CHECK_GOTO(CBB_add_asn1_uint64(&cbb, test->value));
797		CHECK_GOTO(CBB_finish(&cbb, &out, &len));
798		alloc = 0;
799
800		CHECK_GOTO(len == test->encoding_len);
801		CHECK_GOTO(memcmp(out, test->encoding, len) == 0);
802		free(out);
803		out = NULL;
804	}
805
806	for (i = 0; i < sizeof(kAsn1InvalidUint64Tests)
807	    / sizeof(kAsn1InvalidUint64Tests[0]); i++) {
808		const ASN1_INVALID_UINT64_TEST *test =
809		    &kAsn1InvalidUint64Tests[i];
810		CBS cbs;
811		uint64_t value;
812
813		CBS_init(&cbs, (const uint8_t *)test->encoding,
814		    test->encoding_len);
815		CHECK(!CBS_get_asn1_uint64(&cbs, &value));
816	}
817
818	ret = 1;
819
820	if (0) {
821err:
822		if (alloc)
823			CBB_cleanup(&cbb);
824	}
825	free(out);
826
827	return ret;
828}
829
830static int
831test_offset(void)
832{
833	uint8_t v;
834	static const uint8_t input[] = {1, 2, 3, 4, 5};
835	CBS data;
836
837	CBS_init(&data, input, sizeof(input));
838	CHECK(sizeof(input) == 5);
839	CHECK(CBS_len(&data) == 5);
840	CHECK(CBS_offset(&data) == 0);
841	CHECK(CBS_get_u8(&data, &v));
842	CHECK(v == 1);
843	CHECK(CBS_len(&data) == 4);
844	CHECK(CBS_offset(&data) == 1);
845	CHECK(CBS_skip(&data, 2));
846	CHECK(CBS_len(&data) == 2);
847	CHECK(CBS_offset(&data) == 3);
848	CHECK(CBS_get_u8(&data, &v));
849	CHECK(v == 4);
850	CHECK(CBS_get_u8(&data, &v));
851	CHECK(v == 5);
852	CHECK(CBS_len(&data) == 0);
853	CHECK(CBS_offset(&data) == 5);
854	CHECK(!CBS_skip(&data, 1));
855
856	CBS_init(&data, input, sizeof(input));
857	CHECK(CBS_skip(&data, 2));
858	CHECK(CBS_len(&data) == 3);
859	CHECK(CBS_offset(&data) == 2);
860	CHECK(CBS_skip(&data, 3));
861	CHECK(CBS_len(&data) == 0);
862	CHECK(CBS_offset(&data) == 5);
863	CHECK(!CBS_get_u8(&data, &v));
864
865	return 1;
866}
867
868static int
869test_write_bytes(void)
870{
871	int ret = 0;
872	uint8_t v;
873	size_t len;
874	static const uint8_t input[] = {'f', 'o', 'o', 'b', 'a', 'r'};
875	CBS data;
876	uint8_t *tmp = NULL;
877
878	CHECK_GOTO((tmp = malloc(sizeof(input))) != NULL);
879	memset(tmp, 100, sizeof(input));
880
881	CBS_init(&data, input, sizeof(input));
882	CHECK_GOTO(CBS_len(&data) == 6);
883	CHECK_GOTO(CBS_offset(&data) == 0);
884	CHECK_GOTO(CBS_get_u8(&data, &v));
885	CHECK_GOTO(v == 102 /* f */);
886	CHECK_GOTO(CBS_skip(&data, 1));
887	CHECK_GOTO(!CBS_skip(&data, 15));
888	CHECK_GOTO(CBS_write_bytes(&data, tmp, sizeof(input), &len));
889	CHECK_GOTO(len == 4);
890	CHECK_GOTO(memcmp(input + 2, tmp, len) == 0);
891	CHECK_GOTO(tmp[4] == 100 && tmp[5] == 100);
892
893	ret = 1;
894
895err:
896	free(tmp);
897	return ret;
898}
899
900static int
901test_cbs_dup(void)
902{
903	CBS data, check;
904	static const uint8_t input[] = {'f', 'o', 'o', 'b', 'a', 'r'};
905
906	CBS_init(&data, input, sizeof(input));
907	CHECK(CBS_len(&data) == 6);
908	CBS_dup(&data, &check);
909	CHECK(CBS_len(&check) == 6);
910	CHECK(CBS_data(&data) == CBS_data(&check));
911	CHECK(CBS_skip(&data, 1));
912	CHECK(CBS_len(&data) == 5);
913	CHECK(CBS_len(&check) == 6);
914	CHECK(CBS_data(&data) == CBS_data(&check) + 1);
915	CHECK(CBS_skip(&check, 1));
916	CHECK(CBS_len(&data) == 5);
917	CHECK(CBS_len(&check) == 5);
918	CHECK(CBS_data(&data) == CBS_data(&check));
919	CHECK(CBS_offset(&data) == 1);
920	CHECK(CBS_offset(&check) == 1);
921
922	CBS_init(&data, input, sizeof(input));
923	CHECK(CBS_skip(&data, 5));
924	CBS_dup(&data, &check);
925	CHECK(CBS_len(&data) == 1);
926	CHECK(CBS_len(&check) == 1);
927	CHECK(CBS_data(&data) == input + 5);
928	CHECK(CBS_data(&data) == CBS_data(&check));
929	CHECK(CBS_offset(&data) == 5);
930	CHECK(CBS_offset(&check) == 5);
931
932	return 1;
933}
934
935int
936main(void)
937{
938	int failed = 0;
939
940	failed |= !test_skip();
941	failed |= !test_get_u();
942	failed |= !test_get_prefixed();
943	failed |= !test_get_prefixed_bad();
944	failed |= !test_peek_u();
945	failed |= !test_get_asn1();
946	failed |= !test_cbb_basic();
947	failed |= !test_cbb_add_space();
948	failed |= !test_cbb_fixed();
949	failed |= !test_cbb_finish_child();
950	failed |= !test_cbb_discard_child();
951	failed |= !test_cbb_misuse();
952	failed |= !test_cbb_prefixed();
953	failed |= !test_cbb_asn1();
954	failed |= !test_indefinite_convert();
955	failed |= !test_asn1_uint64();
956	failed |= !test_get_optional_asn1_bool();
957	failed |= !test_offset();
958	failed |= !test_write_bytes();
959	failed |= !test_cbs_dup();
960
961	if (!failed)
962		printf("PASS\n");
963	return failed;
964}
965