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