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