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