• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright (c) 2014, Google Inc.
2  *
3  * Permission to use, copy, modify, and/or distribute this software for any
4  * purpose with or without fee is hereby granted, provided that the above
5  * copyright notice and this permission notice appear in all copies.
6  *
7  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
10  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
14 
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 
19 #include <vector>
20 
21 #include <openssl/crypto.h>
22 #include <openssl/bytestring.h>
23 
24 #include "internal.h"
25 #include "../internal.h"
26 #include "../test/scoped_types.h"
27 
28 
TestSkip()29 static bool TestSkip() {
30   static const uint8_t kData[] = {1, 2, 3};
31   CBS data;
32 
33   CBS_init(&data, kData, sizeof(kData));
34   return CBS_len(&data) == 3 &&
35       CBS_skip(&data, 1) &&
36       CBS_len(&data) == 2 &&
37       CBS_skip(&data, 2) &&
38       CBS_len(&data) == 0 &&
39       !CBS_skip(&data, 1);
40 }
41 
TestGetUint()42 static bool TestGetUint() {
43   static const uint8_t kData[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
44   uint8_t u8;
45   uint16_t u16;
46   uint32_t u32;
47   CBS data;
48 
49   CBS_init(&data, kData, sizeof(kData));
50   return CBS_get_u8(&data, &u8) &&
51     u8 == 1 &&
52     CBS_get_u16(&data, &u16) &&
53     u16 == 0x203 &&
54     CBS_get_u24(&data, &u32) &&
55     u32 == 0x40506 &&
56     CBS_get_u32(&data, &u32) &&
57     u32 == 0x708090a &&
58     !CBS_get_u8(&data, &u8);
59 }
60 
TestGetPrefixed()61 static bool TestGetPrefixed() {
62   static const uint8_t kData[] = {1, 2, 0, 2, 3, 4, 0, 0, 3, 3, 2, 1};
63   uint8_t u8;
64   uint16_t u16;
65   uint32_t u32;
66   CBS data, prefixed;
67 
68   CBS_init(&data, kData, sizeof(kData));
69   return CBS_get_u8_length_prefixed(&data, &prefixed) &&
70     CBS_len(&prefixed) == 1 &&
71     CBS_get_u8(&prefixed, &u8) &&
72     u8 == 2 &&
73     CBS_get_u16_length_prefixed(&data, &prefixed) &&
74     CBS_len(&prefixed) == 2 &&
75     CBS_get_u16(&prefixed, &u16) &&
76     u16 == 0x304 &&
77     CBS_get_u24_length_prefixed(&data, &prefixed) &&
78     CBS_len(&prefixed) == 3 &&
79     CBS_get_u24(&prefixed, &u32) &&
80     u32 == 0x30201;
81 }
82 
TestGetPrefixedBad()83 static bool TestGetPrefixedBad() {
84   static const uint8_t kData1[] = {2, 1};
85   static const uint8_t kData2[] = {0, 2, 1};
86   static const uint8_t kData3[] = {0, 0, 2, 1};
87   CBS data, prefixed;
88 
89   CBS_init(&data, kData1, sizeof(kData1));
90   if (CBS_get_u8_length_prefixed(&data, &prefixed)) {
91     return false;
92   }
93 
94   CBS_init(&data, kData2, sizeof(kData2));
95   if (CBS_get_u16_length_prefixed(&data, &prefixed)) {
96     return false;
97   }
98 
99   CBS_init(&data, kData3, sizeof(kData3));
100   if (CBS_get_u24_length_prefixed(&data, &prefixed)) {
101     return false;
102   }
103 
104   return true;
105 }
106 
TestGetASN1()107 static bool TestGetASN1() {
108   static const uint8_t kData1[] = {0x30, 2, 1, 2};
109   static const uint8_t kData2[] = {0x30, 3, 1, 2};
110   static const uint8_t kData3[] = {0x30, 0x80};
111   static const uint8_t kData4[] = {0x30, 0x81, 1, 1};
112   static const uint8_t kData5[] = {0x30, 0x82, 0, 1, 1};
113   static const uint8_t kData6[] = {0xa1, 3, 0x4, 1, 1};
114   static const uint8_t kData7[] = {0xa1, 3, 0x4, 2, 1};
115   static const uint8_t kData8[] = {0xa1, 3, 0x2, 1, 1};
116   static const uint8_t kData9[] = {0xa1, 3, 0x2, 1, 0xff};
117 
118   CBS data, contents;
119   int present;
120   uint64_t value;
121 
122   CBS_init(&data, kData1, sizeof(kData1));
123   if (CBS_peek_asn1_tag(&data, 0x1) ||
124       !CBS_peek_asn1_tag(&data, 0x30)) {
125     return false;
126   }
127   if (!CBS_get_asn1(&data, &contents, 0x30) ||
128       CBS_len(&contents) != 2 ||
129       memcmp(CBS_data(&contents), "\x01\x02", 2) != 0) {
130     return false;
131   }
132 
133   CBS_init(&data, kData2, sizeof(kData2));
134   // data is truncated
135   if (CBS_get_asn1(&data, &contents, 0x30)) {
136     return false;
137   }
138 
139   CBS_init(&data, kData3, sizeof(kData3));
140   // zero byte length of length
141   if (CBS_get_asn1(&data, &contents, 0x30)) {
142     return false;
143   }
144 
145   CBS_init(&data, kData4, sizeof(kData4));
146   // long form mistakenly used.
147   if (CBS_get_asn1(&data, &contents, 0x30)) {
148     return false;
149   }
150 
151   CBS_init(&data, kData5, sizeof(kData5));
152   // length takes too many bytes.
153   if (CBS_get_asn1(&data, &contents, 0x30)) {
154     return false;
155   }
156 
157   CBS_init(&data, kData1, sizeof(kData1));
158   // wrong tag.
159   if (CBS_get_asn1(&data, &contents, 0x31)) {
160     return false;
161   }
162 
163   CBS_init(&data, NULL, 0);
164   // peek at empty data.
165   if (CBS_peek_asn1_tag(&data, 0x30)) {
166     return false;
167   }
168 
169   CBS_init(&data, NULL, 0);
170   // optional elements at empty data.
171   if (!CBS_get_optional_asn1(&data, &contents, &present, 0xa0) ||
172       present ||
173       !CBS_get_optional_asn1_octet_string(&data, &contents, &present, 0xa0) ||
174       present ||
175       CBS_len(&contents) != 0 ||
176       !CBS_get_optional_asn1_octet_string(&data, &contents, NULL, 0xa0) ||
177       CBS_len(&contents) != 0 ||
178       !CBS_get_optional_asn1_uint64(&data, &value, 0xa0, 42) ||
179       value != 42) {
180     return false;
181   }
182 
183   CBS_init(&data, kData6, sizeof(kData6));
184   // optional element.
185   if (!CBS_get_optional_asn1(&data, &contents, &present, 0xa0) ||
186       present ||
187       !CBS_get_optional_asn1(&data, &contents, &present, 0xa1) ||
188       !present ||
189       CBS_len(&contents) != 3 ||
190       memcmp(CBS_data(&contents), "\x04\x01\x01", 3) != 0) {
191     return false;
192   }
193 
194   CBS_init(&data, kData6, sizeof(kData6));
195   // optional octet string.
196   if (!CBS_get_optional_asn1_octet_string(&data, &contents, &present, 0xa0) ||
197       present ||
198       CBS_len(&contents) != 0 ||
199       !CBS_get_optional_asn1_octet_string(&data, &contents, &present, 0xa1) ||
200       !present ||
201       CBS_len(&contents) != 1 ||
202       CBS_data(&contents)[0] != 1) {
203     return false;
204   }
205 
206   CBS_init(&data, kData7, sizeof(kData7));
207   // invalid optional octet string.
208   if (CBS_get_optional_asn1_octet_string(&data, &contents, &present, 0xa1)) {
209     return false;
210   }
211 
212   CBS_init(&data, kData8, sizeof(kData8));
213   // optional octet string.
214   if (!CBS_get_optional_asn1_uint64(&data, &value, 0xa0, 42) ||
215       value != 42 ||
216       !CBS_get_optional_asn1_uint64(&data, &value, 0xa1, 42) ||
217       value != 1) {
218     return false;
219   }
220 
221   CBS_init(&data, kData9, sizeof(kData9));
222   // invalid optional integer.
223   if (CBS_get_optional_asn1_uint64(&data, &value, 0xa1, 42)) {
224     return false;
225   }
226 
227   return true;
228 }
229 
TestGetOptionalASN1Bool()230 static bool TestGetOptionalASN1Bool() {
231   static const uint8_t kTrue[] = {0x0a, 3, CBS_ASN1_BOOLEAN, 1, 0xff};
232   static const uint8_t kFalse[] = {0x0a, 3, CBS_ASN1_BOOLEAN, 1, 0x00};
233   static const uint8_t kInvalid[] = {0x0a, 3, CBS_ASN1_BOOLEAN, 1, 0x01};
234 
235   CBS data;
236   CBS_init(&data, NULL, 0);
237   int val = 2;
238   if (!CBS_get_optional_asn1_bool(&data, &val, 0x0a, 0) ||
239       val != 0) {
240     return false;
241   }
242 
243   CBS_init(&data, kTrue, sizeof(kTrue));
244   val = 2;
245   if (!CBS_get_optional_asn1_bool(&data, &val, 0x0a, 0) ||
246       val != 1) {
247     return false;
248   }
249 
250   CBS_init(&data, kFalse, sizeof(kFalse));
251   val = 2;
252   if (!CBS_get_optional_asn1_bool(&data, &val, 0x0a, 1) ||
253       val != 0) {
254     return false;
255   }
256 
257   CBS_init(&data, kInvalid, sizeof(kInvalid));
258   if (CBS_get_optional_asn1_bool(&data, &val, 0x0a, 1)) {
259     return false;
260   }
261 
262   return true;
263 }
264 
TestCBBBasic()265 static bool TestCBBBasic() {
266   static const uint8_t kExpected[] = {1, 2, 3, 4, 5, 6, 7, 8};
267   uint8_t *buf;
268   size_t buf_len;
269   CBB cbb;
270 
271   if (!CBB_init(&cbb, 100)) {
272     return false;
273   }
274   CBB_cleanup(&cbb);
275 
276   if (!CBB_init(&cbb, 0)) {
277     return false;
278   }
279   if (!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     CBB_cleanup(&cbb);
285     return false;
286   }
287 
288   ScopedOpenSSLBytes scoper(buf);
289   return buf_len == sizeof(kExpected) && memcmp(buf, kExpected, buf_len) == 0;
290 }
291 
TestCBBFixed()292 static bool TestCBBFixed() {
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 false;
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 false;
314   }
315 
316   return true;
317 }
318 
TestCBBFinishChild()319 static bool TestCBBFinishChild() {
320   CBB cbb, child;
321   uint8_t *out_buf;
322   size_t out_size;
323 
324   if (!CBB_init(&cbb, 16)) {
325     return false;
326   }
327   if (!CBB_add_u8_length_prefixed(&cbb, &child) ||
328       CBB_finish(&child, &out_buf, &out_size) ||
329       !CBB_finish(&cbb, &out_buf, &out_size)) {
330     CBB_cleanup(&cbb);
331     return false;
332   }
333   ScopedOpenSSLBytes scoper(out_buf);
334   return out_size == 1 && out_buf[0] == 0;
335 }
336 
TestCBBPrefixed()337 static bool TestCBBPrefixed() {
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 
344   if (!CBB_init(&cbb, 0)) {
345     return false;
346   }
347   if (!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, &inner_inner_contents) ||
358       !CBB_add_u8(&inner_inner_contents, 2) ||
359       !CBB_finish(&cbb, &buf, &buf_len)) {
360     CBB_cleanup(&cbb);
361     return false;
362   }
363 
364   ScopedOpenSSLBytes scoper(buf);
365   return buf_len == sizeof(kExpected) && memcmp(buf, kExpected, buf_len) == 0;
366 }
367 
TestCBBMisuse()368 static bool TestCBBMisuse() {
369   CBB cbb, child, contents;
370   uint8_t *buf;
371   size_t buf_len;
372 
373   if (!CBB_init(&cbb, 0)) {
374     return false;
375   }
376   if (!CBB_add_u8_length_prefixed(&cbb, &child) ||
377       !CBB_add_u8(&child, 1) ||
378       !CBB_add_u8(&cbb, 2)) {
379     CBB_cleanup(&cbb);
380     return false;
381   }
382 
383   // Since we wrote to |cbb|, |child| is now invalid and attempts to write to
384   // it should fail.
385   if (CBB_add_u8(&child, 1) ||
386       CBB_add_u16(&child, 1) ||
387       CBB_add_u24(&child, 1) ||
388       CBB_add_u8_length_prefixed(&child, &contents) ||
389       CBB_add_u16_length_prefixed(&child, &contents) ||
390       CBB_add_asn1(&child, &contents, 1) ||
391       CBB_add_bytes(&child, (const uint8_t*) "a", 1)) {
392     fprintf(stderr, "CBB operation on invalid CBB did not fail.\n");
393     CBB_cleanup(&cbb);
394     return false;
395   }
396 
397   if (!CBB_finish(&cbb, &buf, &buf_len)) {
398     CBB_cleanup(&cbb);
399     return false;
400   }
401   ScopedOpenSSLBytes scoper(buf);
402 
403   if (buf_len != 3 ||
404       memcmp(buf, "\x01\x01\x02", 3) != 0) {
405     return false;
406   }
407   return true;
408 }
409 
TestCBBASN1()410 static bool TestCBBASN1() {
411   static const uint8_t kExpected[] = {0x30, 3, 1, 2, 3};
412   uint8_t *buf;
413   size_t buf_len;
414   CBB cbb, contents, inner_contents;
415 
416   if (!CBB_init(&cbb, 0)) {
417     return false;
418   }
419   if (!CBB_add_asn1(&cbb, &contents, 0x30) ||
420       !CBB_add_bytes(&contents, (const uint8_t*) "\x01\x02\x03", 3) ||
421       !CBB_finish(&cbb, &buf, &buf_len)) {
422     CBB_cleanup(&cbb);
423     return false;
424   }
425   ScopedOpenSSLBytes scoper(buf);
426 
427   if (buf_len != sizeof(kExpected) || memcmp(buf, kExpected, buf_len) != 0) {
428     return false;
429   }
430 
431   std::vector<uint8_t> test_data(100000, 0x42);
432 
433   if (!CBB_init(&cbb, 0)) {
434     return false;
435   }
436   if (!CBB_add_asn1(&cbb, &contents, 0x30) ||
437       !CBB_add_bytes(&contents, bssl::vector_data(&test_data), 130) ||
438       !CBB_finish(&cbb, &buf, &buf_len)) {
439     CBB_cleanup(&cbb);
440     return false;
441   }
442   scoper.reset(buf);
443 
444   if (buf_len != 3 + 130 ||
445       memcmp(buf, "\x30\x81\x82", 3) != 0 ||
446       memcmp(buf + 3, bssl::vector_data(&test_data), 130) != 0) {
447     return false;
448   }
449 
450   if (!CBB_init(&cbb, 0)) {
451     return false;
452   }
453   if (!CBB_add_asn1(&cbb, &contents, 0x30) ||
454       !CBB_add_bytes(&contents, bssl::vector_data(&test_data), 1000) ||
455       !CBB_finish(&cbb, &buf, &buf_len)) {
456     CBB_cleanup(&cbb);
457     return false;
458   }
459   scoper.reset(buf);
460 
461   if (buf_len != 4 + 1000 ||
462       memcmp(buf, "\x30\x82\x03\xe8", 4) != 0 ||
463       memcmp(buf + 4, bssl::vector_data(&test_data), 1000)) {
464     return false;
465   }
466 
467   if (!CBB_init(&cbb, 0)) {
468     return false;
469   }
470   if (!CBB_add_asn1(&cbb, &contents, 0x30) ||
471       !CBB_add_asn1(&contents, &inner_contents, 0x30) ||
472       !CBB_add_bytes(&inner_contents, bssl::vector_data(&test_data), 100000) ||
473       !CBB_finish(&cbb, &buf, &buf_len)) {
474     CBB_cleanup(&cbb);
475     return false;
476   }
477   scoper.reset(buf);
478 
479   if (buf_len != 5 + 5 + 100000 ||
480       memcmp(buf, "\x30\x83\x01\x86\xa5\x30\x83\x01\x86\xa0", 10) != 0 ||
481       memcmp(buf + 10, bssl::vector_data(&test_data), 100000)) {
482     return false;
483   }
484 
485   return true;
486 }
487 
DoBerConvert(const char * name,const uint8_t * der_expected,size_t der_len,const uint8_t * ber,size_t ber_len)488 static bool DoBerConvert(const char *name,
489                          const uint8_t *der_expected, size_t der_len,
490                          const uint8_t *ber, size_t ber_len) {
491   CBS in;
492   uint8_t *out;
493   size_t out_len;
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     return false;
499   }
500   ScopedOpenSSLBytes scoper(out);
501 
502   if (out == NULL) {
503     if (ber_len != der_len ||
504         memcmp(der_expected, ber, ber_len) != 0) {
505       fprintf(stderr, "%s: incorrect unconverted result.\n", name);
506       return false;
507     }
508 
509     return true;
510   }
511 
512   if (out_len != der_len ||
513       memcmp(out, der_expected, der_len) != 0) {
514     fprintf(stderr, "%s: incorrect converted result.\n", name);
515     return false;
516   }
517 
518   return true;
519 }
520 
TestBerConvert()521 static bool TestBerConvert() {
522   static const uint8_t kSimpleBER[] = {0x01, 0x01, 0x00};
523 
524   // kIndefBER contains a SEQUENCE with an indefinite length.
525   static const uint8_t kIndefBER[] = {0x30, 0x80, 0x01, 0x01, 0x02, 0x00, 0x00};
526   static const uint8_t kIndefDER[] = {0x30, 0x03, 0x01, 0x01, 0x02};
527 
528   // kOctetStringBER contains an indefinite length OCTETSTRING with two parts.
529   // These parts need to be concatenated in DER form.
530   static const uint8_t kOctetStringBER[] = {0x24, 0x80, 0x04, 0x02, 0,    1,
531                                             0x04, 0x02, 2,    3,    0x00, 0x00};
532   static const uint8_t kOctetStringDER[] = {0x04, 0x04, 0, 1, 2, 3};
533 
534   // kNSSBER is part of a PKCS#12 message generated by NSS that uses indefinite
535   // length elements extensively.
536   static const uint8_t kNSSBER[] = {
537       0x30, 0x80, 0x02, 0x01, 0x03, 0x30, 0x80, 0x06, 0x09, 0x2a, 0x86, 0x48,
538       0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x80, 0x24, 0x80, 0x04, 0x04,
539       0x01, 0x02, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x39,
540       0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05,
541       0x00, 0x04, 0x14, 0x84, 0x98, 0xfc, 0x66, 0x33, 0xee, 0xba, 0xe7, 0x90,
542       0xc1, 0xb6, 0xe8, 0x8f, 0xfe, 0x1d, 0xc5, 0xa5, 0x97, 0x93, 0x3e, 0x04,
543       0x10, 0x38, 0x62, 0xc6, 0x44, 0x12, 0xd5, 0x30, 0x00, 0xf8, 0xf2, 0x1b,
544       0xf0, 0x6e, 0x10, 0x9b, 0xb8, 0x02, 0x02, 0x07, 0xd0, 0x00, 0x00,
545   };
546 
547   static const uint8_t kNSSDER[] = {
548       0x30, 0x53, 0x02, 0x01, 0x03, 0x30, 0x13, 0x06, 0x09, 0x2a, 0x86,
549       0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x06, 0x04, 0x04,
550       0x01, 0x02, 0x03, 0x04, 0x30, 0x39, 0x30, 0x21, 0x30, 0x09, 0x06,
551       0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14, 0x84,
552       0x98, 0xfc, 0x66, 0x33, 0xee, 0xba, 0xe7, 0x90, 0xc1, 0xb6, 0xe8,
553       0x8f, 0xfe, 0x1d, 0xc5, 0xa5, 0x97, 0x93, 0x3e, 0x04, 0x10, 0x38,
554       0x62, 0xc6, 0x44, 0x12, 0xd5, 0x30, 0x00, 0xf8, 0xf2, 0x1b, 0xf0,
555       0x6e, 0x10, 0x9b, 0xb8, 0x02, 0x02, 0x07, 0xd0,
556   };
557 
558   return DoBerConvert("kSimpleBER", kSimpleBER, sizeof(kSimpleBER),
559                       kSimpleBER, sizeof(kSimpleBER)) &&
560          DoBerConvert("kIndefBER", kIndefDER, sizeof(kIndefDER), kIndefBER,
561                       sizeof(kIndefBER)) &&
562          DoBerConvert("kOctetStringBER", kOctetStringDER,
563                       sizeof(kOctetStringDER), kOctetStringBER,
564                       sizeof(kOctetStringBER)) &&
565          DoBerConvert("kNSSBER", kNSSDER, sizeof(kNSSDER), kNSSBER,
566                       sizeof(kNSSBER));
567 }
568 
569 struct ASN1Uint64Test {
570   uint64_t value;
571   const char *encoding;
572   size_t encoding_len;
573 };
574 
575 static const ASN1Uint64Test kASN1Uint64Tests[] = {
576     {0, "\x02\x01\x00", 3},
577     {1, "\x02\x01\x01", 3},
578     {127, "\x02\x01\x7f", 3},
579     {128, "\x02\x02\x00\x80", 4},
580     {0xdeadbeef, "\x02\x05\x00\xde\xad\xbe\xef", 7},
581     {OPENSSL_U64(0x0102030405060708),
582      "\x02\x08\x01\x02\x03\x04\x05\x06\x07\x08", 10},
583     {OPENSSL_U64(0xffffffffffffffff),
584       "\x02\x09\x00\xff\xff\xff\xff\xff\xff\xff\xff", 11},
585 };
586 
587 struct ASN1InvalidUint64Test {
588   const char *encoding;
589   size_t encoding_len;
590 };
591 
592 static const ASN1InvalidUint64Test kASN1InvalidUint64Tests[] = {
593     // Bad tag.
594     {"\x03\x01\x00", 3},
595     // Empty contents.
596     {"\x02\x00", 2},
597     // Negative number.
598     {"\x02\x01\x80", 3},
599     // Overflow.
600     {"\x02\x09\x01\x00\x00\x00\x00\x00\x00\x00\x00", 11},
601     // Leading zeros.
602     {"\x02\x02\x00\x01", 4},
603 };
604 
TestASN1Uint64()605 static bool TestASN1Uint64() {
606   for (size_t i = 0; i < sizeof(kASN1Uint64Tests) / sizeof(kASN1Uint64Tests[0]);
607        i++) {
608     const ASN1Uint64Test *test = &kASN1Uint64Tests[i];
609     CBS cbs;
610     uint64_t value;
611     CBB cbb;
612     uint8_t *out;
613     size_t len;
614 
615     CBS_init(&cbs, (const uint8_t *)test->encoding, test->encoding_len);
616     if (!CBS_get_asn1_uint64(&cbs, &value) ||
617         CBS_len(&cbs) != 0 ||
618         value != test->value) {
619       return false;
620     }
621 
622     if (!CBB_init(&cbb, 0)) {
623       return false;
624     }
625     if (!CBB_add_asn1_uint64(&cbb, test->value) ||
626         !CBB_finish(&cbb, &out, &len)) {
627       CBB_cleanup(&cbb);
628       return false;
629     }
630     ScopedOpenSSLBytes scoper(out);
631     if (len != test->encoding_len || memcmp(out, test->encoding, len) != 0) {
632       return false;
633     }
634   }
635 
636   for (size_t i = 0;
637        i < sizeof(kASN1InvalidUint64Tests) / sizeof(kASN1InvalidUint64Tests[0]);
638        i++) {
639     const ASN1InvalidUint64Test *test = &kASN1InvalidUint64Tests[i];
640     CBS cbs;
641     uint64_t value;
642 
643     CBS_init(&cbs, (const uint8_t *)test->encoding, test->encoding_len);
644     if (CBS_get_asn1_uint64(&cbs, &value)) {
645       return false;
646     }
647   }
648 
649   return true;
650 }
651 
main(void)652 int main(void) {
653   CRYPTO_library_init();
654 
655   if (!TestSkip() ||
656       !TestGetUint() ||
657       !TestGetPrefixed() ||
658       !TestGetPrefixedBad() ||
659       !TestGetASN1() ||
660       !TestCBBBasic() ||
661       !TestCBBFixed() ||
662       !TestCBBFinishChild() ||
663       !TestCBBMisuse() ||
664       !TestCBBPrefixed() ||
665       !TestCBBASN1() ||
666       !TestBerConvert() ||
667       !TestASN1Uint64() ||
668       !TestGetOptionalASN1Bool()) {
669     return 1;
670   }
671 
672   printf("PASS\n");
673   return 0;
674 }
675