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