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