bytestringtest.c revision 1.3
1/*	$OpenBSD: bytestringtest.c,v 1.3 2015/02/16 06:48:17 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_ber_convert(const char *name, const uint8_t *der_expected, size_t der_len,
488    const uint8_t *ber, size_t ber_len)
489{
490	CBS in;
491	uint8_t *out = NULL;
492	size_t out_len;
493	int ret = 0;
494
495	CBS_init(&in, ber, ber_len);
496	if (!CBS_asn1_ber_to_der(&in, &out, &out_len)) {
497		fprintf(stderr, "%s: CBS_asn1_ber_to_der failed.\n", name);
498		goto end;
499	}
500
501	if (out == NULL) {
502		if (ber_len != der_len ||
503		    memcmp(der_expected, ber, ber_len) != 0) {
504			fprintf(stderr, "%s: incorrect unconverted result.\n",
505			    name);
506			return 0;
507		}
508
509		return 1;
510	}
511
512	if (out_len != der_len || memcmp(out, der_expected, der_len) != 0) {
513		fprintf(stderr, "%s: incorrect converted result.\n", name);
514		goto end;
515	}
516
517	ret = 1;
518
519end:
520	free(out);
521	return ret;
522}
523
524static int
525test_ber_convert(void)
526{
527	static const uint8_t kSimpleBER[] = {0x01, 0x01, 0x00};
528
529	/* kIndefBER contains a SEQUENCE with an indefinite length. */
530	static const uint8_t kIndefBER[] = {0x30, 0x80, 0x01, 0x01, 0x02, 0x00,
531	    0x00};
532	static const uint8_t kIndefDER[] = {0x30, 0x03, 0x01, 0x01, 0x02};
533
534	/*
535	 * kOctetStringBER contains an indefinite length OCTETSTRING with two
536	 * parts.  These parts need to be concatenated in DER form.
537	 */
538	static const uint8_t kOctetStringBER[] = {0x24, 0x80, 0x04, 0x02, 0,
539	    1, 0x04, 0x02, 2,    3,    0x00, 0x00};
540	static const uint8_t kOctetStringDER[] = {0x04, 0x04, 0, 1, 2, 3};
541
542	/*
543	 * kNSSBER is part of a PKCS#12 message generated by NSS that uses
544	 * indefinite length elements extensively.
545	 */
546	static const uint8_t kNSSBER[] = {
547	    0x30, 0x80, 0x02, 0x01, 0x03, 0x30, 0x80, 0x06, 0x09, 0x2a, 0x86,
548	    0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x80, 0x24, 0x80,
549	    0x04, 0x04, 0x01, 0x02, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
550	    0x00, 0x30, 0x39, 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e,
551	    0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14, 0x84, 0x98, 0xfc, 0x66,
552	    0x33, 0xee, 0xba, 0xe7, 0x90, 0xc1, 0xb6, 0xe8, 0x8f, 0xfe, 0x1d,
553	    0xc5, 0xa5, 0x97, 0x93, 0x3e, 0x04, 0x10, 0x38, 0x62, 0xc6, 0x44,
554	    0x12, 0xd5, 0x30, 0x00, 0xf8, 0xf2, 0x1b, 0xf0, 0x6e, 0x10, 0x9b,
555	    0xb8, 0x02, 0x02, 0x07, 0xd0, 0x00, 0x00,
556	};
557
558	static const uint8_t kNSSDER[] = {
559	    0x30, 0x53, 0x02, 0x01, 0x03, 0x30, 0x13, 0x06, 0x09, 0x2a, 0x86,
560	    0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x06, 0x04, 0x04,
561	    0x01, 0x02, 0x03, 0x04, 0x30, 0x39, 0x30, 0x21, 0x30, 0x09, 0x06,
562	    0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14, 0x84,
563	    0x98, 0xfc, 0x66, 0x33, 0xee, 0xba, 0xe7, 0x90, 0xc1, 0xb6, 0xe8,
564	    0x8f, 0xfe, 0x1d, 0xc5, 0xa5, 0x97, 0x93, 0x3e, 0x04, 0x10, 0x38,
565	    0x62, 0xc6, 0x44, 0x12, 0xd5, 0x30, 0x00, 0xf8, 0xf2, 0x1b, 0xf0,
566	    0x6e, 0x10, 0x9b, 0xb8, 0x02, 0x02, 0x07, 0xd0,
567	};
568
569	return do_ber_convert("kSimpleBER", kSimpleBER, sizeof(kSimpleBER),
570	    kSimpleBER, sizeof(kSimpleBER)) &&
571	    do_ber_convert("kIndefBER", kIndefDER, sizeof(kIndefDER), kIndefBER,
572	    sizeof(kIndefBER)) &&
573	    do_ber_convert("kOctetStringBER", kOctetStringDER,
574	    sizeof(kOctetStringDER), kOctetStringBER,
575	    sizeof(kOctetStringBER)) &&
576	    do_ber_convert("kNSSBER", kNSSDER, sizeof(kNSSDER), kNSSBER,
577	    sizeof(kNSSBER));
578}
579
580typedef struct {
581	uint64_t value;
582	const char *encoding;
583	size_t encoding_len;
584} ASN1_UINT64_TEST;
585
586static const ASN1_UINT64_TEST kAsn1Uint64Tests[] = {
587	{0, "\x02\x01\x00", 3},
588	{1, "\x02\x01\x01", 3},
589	{127, "\x02\x01\x7f", 3},
590	{128, "\x02\x02\x00\x80", 4},
591	{0xdeadbeef, "\x02\x05\x00\xde\xad\xbe\xef", 7},
592	{OPENSSL_U64(0x0102030405060708),
593	    "\x02\x08\x01\x02\x03\x04\x05\x06\x07\x08", 10},
594	{OPENSSL_U64(0xffffffffffffffff),
595	    "\x02\x09\x00\xff\xff\xff\xff\xff\xff\xff\xff", 11},
596};
597
598typedef struct {
599	const char *encoding;
600	size_t encoding_len;
601} ASN1_INVALID_UINT64_TEST;
602
603static const ASN1_INVALID_UINT64_TEST kAsn1InvalidUint64Tests[] = {
604	/* Bad tag. */
605	{"\x03\x01\x00", 3},
606	/* Empty contents. */
607	{"\x02\x00", 2},
608	/* Negative number. */
609	{"\x02\x01\x80", 3},
610	/* Overflow */
611	{"\x02\x09\x01\x00\x00\x00\x00\x00\x00\x00\x00", 11},
612};
613
614static int
615test_asn1_uint64(void)
616{
617	size_t i;
618
619	for (i = 0; i < sizeof(kAsn1Uint64Tests) / sizeof(kAsn1Uint64Tests[0]);
620	     i++) {
621		const ASN1_UINT64_TEST *test = &kAsn1Uint64Tests[i];
622		CBS cbs;
623		uint64_t value;
624		CBB cbb;
625		uint8_t *out;
626		size_t len;
627
628		CBS_init(&cbs, (const uint8_t *)test->encoding,
629		    test->encoding_len);
630
631		if (!CBS_get_asn1_uint64(&cbs, &value) ||
632		    CBS_len(&cbs) != 0 ||
633		    value != test->value)
634			return 0;
635
636		if (!CBB_init(&cbb, 0))
637			return 0;
638
639		if (!CBB_add_asn1_uint64(&cbb, test->value) ||
640		    !CBB_finish(&cbb, &out, &len)) {
641			CBB_cleanup(&cbb);
642			return 0;
643		}
644
645		if (len != test->encoding_len || memcmp(out, test->encoding,
646		    len) != 0) {
647			free(out);
648			return 0;
649		}
650		free(out);
651	}
652
653	for (i = 0; i < sizeof(kAsn1InvalidUint64Tests)
654	    / sizeof(kAsn1InvalidUint64Tests[0]); i++) {
655		const ASN1_INVALID_UINT64_TEST *test =
656		    &kAsn1InvalidUint64Tests[i];
657		CBS cbs;
658		uint64_t value;
659
660		CBS_init(&cbs, (const uint8_t *)test->encoding,
661		    test->encoding_len);
662		if (CBS_get_asn1_uint64(&cbs, &value))
663			return 0;
664	}
665
666	return 1;
667}
668
669int
670main(void)
671{
672	if (!test_skip() ||
673	    !test_get_u() ||
674	    !test_get_prefixed() ||
675	    !test_get_prefixed_bad() ||
676	    !test_get_asn1() ||
677	    !test_cbb_basic() ||
678	    !test_cbb_fixed() ||
679	    !test_cbb_finish_child() ||
680	    !test_cbb_misuse() ||
681	    !test_cbb_prefixed() ||
682	    !test_cbb_asn1() ||
683	    !test_ber_convert() ||
684	    !test_asn1_uint64() ||
685	    !test_get_optional_asn1_bool())
686		return 1;
687
688	printf("PASS\n");
689	return 0;
690}
691