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