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