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