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