1 /* Copyright (c) 2014, Google Inc.
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.
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. */
18 #include <openssl/crypto.h>
19 #include <openssl/bytestring.h>
22 #include "../internal.h"
25 static int test_skip(void) {
26 static const uint8_t kData[] = {1, 2, 3};
29 CBS_init(&data, kData, sizeof(kData));
30 return CBS_len(&data) == 3 &&
32 CBS_len(&data) == 2 &&
34 CBS_len(&data) == 0 &&
38 static int test_get_u(void) {
39 static const uint8_t kData[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
45 CBS_init(&data, kData, sizeof(kData));
46 return CBS_get_u8(&data, &u8) &&
48 CBS_get_u16(&data, &u16) &&
50 CBS_get_u24(&data, &u32) &&
52 CBS_get_u32(&data, &u32) &&
54 !CBS_get_u8(&data, &u8);
57 static int test_get_prefixed(void) {
58 static const uint8_t kData[] = {1, 2, 0, 2, 3, 4, 0, 0, 3, 3, 2, 1};
64 CBS_init(&data, kData, sizeof(kData));
65 return CBS_get_u8_length_prefixed(&data, &prefixed) &&
66 CBS_len(&prefixed) == 1 &&
67 CBS_get_u8(&prefixed, &u8) &&
69 CBS_get_u16_length_prefixed(&data, &prefixed) &&
70 CBS_len(&prefixed) == 2 &&
71 CBS_get_u16(&prefixed, &u16) &&
73 CBS_get_u24_length_prefixed(&data, &prefixed) &&
74 CBS_len(&prefixed) == 3 &&
75 CBS_get_u24(&prefixed, &u32) &&
79 static int test_get_prefixed_bad(void) {
80 static const uint8_t kData1[] = {2, 1};
81 static const uint8_t kData2[] = {0, 2, 1};
82 static const uint8_t kData3[] = {0, 0, 2, 1};
85 CBS_init(&data, kData1, sizeof(kData1));
86 if (CBS_get_u8_length_prefixed(&data, &prefixed)) {
90 CBS_init(&data, kData2, sizeof(kData2));
91 if (CBS_get_u16_length_prefixed(&data, &prefixed)) {
95 CBS_init(&data, kData3, sizeof(kData3));
96 if (CBS_get_u24_length_prefixed(&data, &prefixed)) {
103 static int test_get_asn1(void) {
104 static const uint8_t kData1[] = {0x30, 2, 1, 2};
105 static const uint8_t kData2[] = {0x30, 3, 1, 2};
106 static const uint8_t kData3[] = {0x30, 0x80};
107 static const uint8_t kData4[] = {0x30, 0x81, 1, 1};
108 static const uint8_t kData5[] = {0x30, 0x82, 0, 1, 1};
109 static const uint8_t kData6[] = {0xa1, 3, 0x4, 1, 1};
110 static const uint8_t kData7[] = {0xa1, 3, 0x4, 2, 1};
111 static const uint8_t kData8[] = {0xa1, 3, 0x2, 1, 1};
112 static const uint8_t kData9[] = {0xa1, 3, 0x2, 1, 0xff};
118 CBS_init(&data, kData1, sizeof(kData1));
119 if (CBS_peek_asn1_tag(&data, 0x1) ||
120 !CBS_peek_asn1_tag(&data, 0x30)) {
123 if (!CBS_get_asn1(&data, &contents, 0x30) ||
124 CBS_len(&contents) != 2 ||
125 memcmp(CBS_data(&contents), "\x01\x02", 2) != 0) {
129 CBS_init(&data, kData2, sizeof(kData2));
130 /* data is truncated */
131 if (CBS_get_asn1(&data, &contents, 0x30)) {
135 CBS_init(&data, kData3, sizeof(kData3));
136 /* zero byte length of length */
137 if (CBS_get_asn1(&data, &contents, 0x30)) {
141 CBS_init(&data, kData4, sizeof(kData4));
142 /* long form mistakenly used. */
143 if (CBS_get_asn1(&data, &contents, 0x30)) {
147 CBS_init(&data, kData5, sizeof(kData5));
148 /* length takes too many bytes. */
149 if (CBS_get_asn1(&data, &contents, 0x30)) {
153 CBS_init(&data, kData1, sizeof(kData1));
155 if (CBS_get_asn1(&data, &contents, 0x31)) {
159 CBS_init(&data, NULL, 0);
160 /* peek at empty data. */
161 if (CBS_peek_asn1_tag(&data, 0x30)) {
165 CBS_init(&data, NULL, 0);
166 /* optional elements at empty data. */
167 if (!CBS_get_optional_asn1(&data, &contents, &present, 0xa0) ||
169 !CBS_get_optional_asn1_octet_string(&data, &contents, &present, 0xa0) ||
171 CBS_len(&contents) != 0 ||
172 !CBS_get_optional_asn1_octet_string(&data, &contents, NULL, 0xa0) ||
173 CBS_len(&contents) != 0 ||
174 !CBS_get_optional_asn1_uint64(&data, &value, 0xa0, 42) ||
179 CBS_init(&data, kData6, sizeof(kData6));
180 /* optional element. */
181 if (!CBS_get_optional_asn1(&data, &contents, &present, 0xa0) ||
183 !CBS_get_optional_asn1(&data, &contents, &present, 0xa1) ||
185 CBS_len(&contents) != 3 ||
186 memcmp(CBS_data(&contents), "\x04\x01\x01", 3) != 0) {
190 CBS_init(&data, kData6, sizeof(kData6));
191 /* optional octet string. */
192 if (!CBS_get_optional_asn1_octet_string(&data, &contents, &present, 0xa0) ||
194 CBS_len(&contents) != 0 ||
195 !CBS_get_optional_asn1_octet_string(&data, &contents, &present, 0xa1) ||
197 CBS_len(&contents) != 1 ||
198 CBS_data(&contents)[0] != 1) {
202 CBS_init(&data, kData7, sizeof(kData7));
203 /* invalid optional octet string. */
204 if (CBS_get_optional_asn1_octet_string(&data, &contents, &present, 0xa1)) {
208 CBS_init(&data, kData8, sizeof(kData8));
209 /* optional octet string. */
210 if (!CBS_get_optional_asn1_uint64(&data, &value, 0xa0, 42) ||
212 !CBS_get_optional_asn1_uint64(&data, &value, 0xa1, 42) ||
217 CBS_init(&data, kData9, sizeof(kData9));
218 /* invalid optional integer. */
219 if (CBS_get_optional_asn1_uint64(&data, &value, 0xa1, 42)) {
226 static int test_get_optional_asn1_bool(void) {
230 static const uint8_t kTrue[] = {0x0a, 3, CBS_ASN1_BOOLEAN, 1, 0xff};
231 static const uint8_t kFalse[] = {0x0a, 3, CBS_ASN1_BOOLEAN, 1, 0x00};
232 static const uint8_t kInvalid[] = {0x0a, 3, CBS_ASN1_BOOLEAN, 1, 0x01};
234 CBS_init(&data, NULL, 0);
236 if (!CBS_get_optional_asn1_bool(&data, &val, 0x0a, 0) ||
241 CBS_init(&data, kTrue, sizeof(kTrue));
243 if (!CBS_get_optional_asn1_bool(&data, &val, 0x0a, 0) ||
248 CBS_init(&data, kFalse, sizeof(kFalse));
250 if (!CBS_get_optional_asn1_bool(&data, &val, 0x0a, 1) ||
255 CBS_init(&data, kInvalid, sizeof(kInvalid));
256 if (CBS_get_optional_asn1_bool(&data, &val, 0x0a, 1)) {
263 static int test_cbb_basic(void) {
264 static const uint8_t kExpected[] = {1, 2, 3, 4, 5, 6, 7, 8};
270 if (!CBB_init(&cbb, 100)) {
275 if (!CBB_init(&cbb, 0) ||
276 !CBB_add_u8(&cbb, 1) ||
277 !CBB_add_u16(&cbb, 0x203) ||
278 !CBB_add_u24(&cbb, 0x40506) ||
279 !CBB_add_bytes(&cbb, (const uint8_t*) "\x07\x08", 2) ||
280 !CBB_finish(&cbb, &buf, &buf_len)) {
284 ok = buf_len == sizeof(kExpected) && memcmp(buf, kExpected, buf_len) == 0;
289 static int test_cbb_fixed(void) {
295 if (!CBB_init_fixed(&cbb, NULL, 0) ||
296 CBB_add_u8(&cbb, 1) ||
297 !CBB_finish(&cbb, &out_buf, &out_size) ||
303 if (!CBB_init_fixed(&cbb, buf, 1) ||
304 !CBB_add_u8(&cbb, 1) ||
305 CBB_add_u8(&cbb, 2) ||
306 !CBB_finish(&cbb, &out_buf, &out_size) ||
316 static int test_cbb_finish_child(void) {
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) ||
334 static int test_cbb_prefixed(void) {
335 static const uint8_t kExpected[] = {0, 1, 1, 0, 2, 2, 3, 0, 0, 3,
336 4, 5, 6, 5, 4, 1, 0, 1, 2};
339 CBB cbb, contents, inner_contents, inner_inner_contents;
342 if (!CBB_init(&cbb, 0) ||
343 !CBB_add_u8_length_prefixed(&cbb, &contents) ||
344 !CBB_add_u8_length_prefixed(&cbb, &contents) ||
345 !CBB_add_u8(&contents, 1) ||
346 !CBB_add_u16_length_prefixed(&cbb, &contents) ||
347 !CBB_add_u16(&contents, 0x203) ||
348 !CBB_add_u24_length_prefixed(&cbb, &contents) ||
349 !CBB_add_u24(&contents, 0x40506) ||
350 !CBB_add_u8_length_prefixed(&cbb, &contents) ||
351 !CBB_add_u8_length_prefixed(&contents, &inner_contents) ||
352 !CBB_add_u8(&inner_contents, 1) ||
353 !CBB_add_u16_length_prefixed(&inner_contents, &inner_inner_contents) ||
354 !CBB_add_u8(&inner_inner_contents, 2) ||
355 !CBB_finish(&cbb, &buf, &buf_len)) {
359 ok = buf_len == sizeof(kExpected) && memcmp(buf, kExpected, buf_len) == 0;
364 static int test_cbb_misuse(void) {
365 CBB cbb, child, contents;
369 if (!CBB_init(&cbb, 0) ||
370 !CBB_add_u8_length_prefixed(&cbb, &child) ||
371 !CBB_add_u8(&child, 1) ||
372 !CBB_add_u8(&cbb, 2)) {
376 /* Since we wrote to |cbb|, |child| is now invalid and attempts to write to
378 if (CBB_add_u8(&child, 1) ||
379 CBB_add_u16(&child, 1) ||
380 CBB_add_u24(&child, 1) ||
381 CBB_add_u8_length_prefixed(&child, &contents) ||
382 CBB_add_u16_length_prefixed(&child, &contents) ||
383 CBB_add_asn1(&child, &contents, 1) ||
384 CBB_add_bytes(&child, (const uint8_t*) "a", 1)) {
385 fprintf(stderr, "CBB operation on invalid CBB did not fail.\n");
389 if (!CBB_finish(&cbb, &buf, &buf_len) ||
391 memcmp(buf, "\x01\x01\x02", 3) != 0) {
400 static int test_cbb_asn1(void) {
401 static const uint8_t kExpected[] = {0x30, 3, 1, 2, 3};
402 uint8_t *buf, *test_data;
404 CBB cbb, contents, inner_contents;
406 if (!CBB_init(&cbb, 0) ||
407 !CBB_add_asn1(&cbb, &contents, 0x30) ||
408 !CBB_add_bytes(&contents, (const uint8_t*) "\x01\x02\x03", 3) ||
409 !CBB_finish(&cbb, &buf, &buf_len)) {
413 if (buf_len != sizeof(kExpected) || memcmp(buf, kExpected, buf_len) != 0) {
418 test_data = malloc(100000);
419 memset(test_data, 0x42, 100000);
421 if (!CBB_init(&cbb, 0) ||
422 !CBB_add_asn1(&cbb, &contents, 0x30) ||
423 !CBB_add_bytes(&contents, test_data, 130) ||
424 !CBB_finish(&cbb, &buf, &buf_len)) {
428 if (buf_len != 3 + 130 ||
429 memcmp(buf, "\x30\x81\x82", 3) != 0 ||
430 memcmp(buf + 3, test_data, 130) != 0) {
435 if (!CBB_init(&cbb, 0) ||
436 !CBB_add_asn1(&cbb, &contents, 0x30) ||
437 !CBB_add_bytes(&contents, test_data, 1000) ||
438 !CBB_finish(&cbb, &buf, &buf_len)) {
442 if (buf_len != 4 + 1000 ||
443 memcmp(buf, "\x30\x82\x03\xe8", 4) != 0 ||
444 memcmp(buf + 4, test_data, 1000)) {
449 if (!CBB_init(&cbb, 0) ||
450 !CBB_add_asn1(&cbb, &contents, 0x30) ||
451 !CBB_add_asn1(&contents, &inner_contents, 0x30) ||
452 !CBB_add_bytes(&inner_contents, test_data, 100000) ||
453 !CBB_finish(&cbb, &buf, &buf_len)) {
457 if (buf_len != 5 + 5 + 100000 ||
458 memcmp(buf, "\x30\x83\x01\x86\xa5\x30\x83\x01\x86\xa0", 10) != 0 ||
459 memcmp(buf + 10, test_data, 100000)) {
468 static int do_ber_convert(const char *name,
469 const uint8_t *der_expected, size_t der_len,
470 const uint8_t *ber, size_t ber_len) {
475 CBS_init(&in, ber, ber_len);
476 if (!CBS_asn1_ber_to_der(&in, &out, &out_len)) {
477 fprintf(stderr, "%s: CBS_asn1_ber_to_der failed.\n", name);
482 if (ber_len != der_len ||
483 memcmp(der_expected, ber, ber_len) != 0) {
484 fprintf(stderr, "%s: incorrect unconverted result.\n", name);
491 if (out_len != der_len ||
492 memcmp(out, der_expected, der_len) != 0) {
493 fprintf(stderr, "%s: incorrect converted result.\n", name);
501 static int test_ber_convert(void) {
502 static const uint8_t kSimpleBER[] = {0x01, 0x01, 0x00};
504 /* kIndefBER contains a SEQUENCE with an indefinite length. */
505 static const uint8_t kIndefBER[] = {0x30, 0x80, 0x01, 0x01, 0x02, 0x00, 0x00};
506 static const uint8_t kIndefDER[] = {0x30, 0x03, 0x01, 0x01, 0x02};
508 /* kOctetStringBER contains an indefinite length OCTETSTRING with two parts.
509 * These parts need to be concatenated in DER form. */
510 static const uint8_t kOctetStringBER[] = {0x24, 0x80, 0x04, 0x02, 0, 1,
511 0x04, 0x02, 2, 3, 0x00, 0x00};
512 static const uint8_t kOctetStringDER[] = {0x04, 0x04, 0, 1, 2, 3};
514 /* kNSSBER is part of a PKCS#12 message generated by NSS that uses indefinite
515 * length elements extensively. */
516 static const uint8_t kNSSBER[] = {
517 0x30, 0x80, 0x02, 0x01, 0x03, 0x30, 0x80, 0x06, 0x09, 0x2a, 0x86, 0x48,
518 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x80, 0x24, 0x80, 0x04, 0x04,
519 0x01, 0x02, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x39,
520 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05,
521 0x00, 0x04, 0x14, 0x84, 0x98, 0xfc, 0x66, 0x33, 0xee, 0xba, 0xe7, 0x90,
522 0xc1, 0xb6, 0xe8, 0x8f, 0xfe, 0x1d, 0xc5, 0xa5, 0x97, 0x93, 0x3e, 0x04,
523 0x10, 0x38, 0x62, 0xc6, 0x44, 0x12, 0xd5, 0x30, 0x00, 0xf8, 0xf2, 0x1b,
524 0xf0, 0x6e, 0x10, 0x9b, 0xb8, 0x02, 0x02, 0x07, 0xd0, 0x00, 0x00,
527 static const uint8_t kNSSDER[] = {
528 0x30, 0x53, 0x02, 0x01, 0x03, 0x30, 0x13, 0x06, 0x09, 0x2a, 0x86,
529 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x06, 0x04, 0x04,
530 0x01, 0x02, 0x03, 0x04, 0x30, 0x39, 0x30, 0x21, 0x30, 0x09, 0x06,
531 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14, 0x84,
532 0x98, 0xfc, 0x66, 0x33, 0xee, 0xba, 0xe7, 0x90, 0xc1, 0xb6, 0xe8,
533 0x8f, 0xfe, 0x1d, 0xc5, 0xa5, 0x97, 0x93, 0x3e, 0x04, 0x10, 0x38,
534 0x62, 0xc6, 0x44, 0x12, 0xd5, 0x30, 0x00, 0xf8, 0xf2, 0x1b, 0xf0,
535 0x6e, 0x10, 0x9b, 0xb8, 0x02, 0x02, 0x07, 0xd0,
538 return do_ber_convert("kSimpleBER", kSimpleBER, sizeof(kSimpleBER),
539 kSimpleBER, sizeof(kSimpleBER)) &&
540 do_ber_convert("kIndefBER", kIndefDER, sizeof(kIndefDER), kIndefBER,
541 sizeof(kIndefBER)) &&
542 do_ber_convert("kOctetStringBER", kOctetStringDER,
543 sizeof(kOctetStringDER), kOctetStringBER,
544 sizeof(kOctetStringBER)) &&
545 do_ber_convert("kNSSBER", kNSSDER, sizeof(kNSSDER), kNSSBER,
551 const char *encoding;
555 static const ASN1_UINT64_TEST kAsn1Uint64Tests[] = {
556 {0, "\x02\x01\x00", 3},
557 {1, "\x02\x01\x01", 3},
558 {127, "\x02\x01\x7f", 3},
559 {128, "\x02\x02\x00\x80", 4},
560 {0xdeadbeef, "\x02\x05\x00\xde\xad\xbe\xef", 7},
561 {OPENSSL_U64(0x0102030405060708),
562 "\x02\x08\x01\x02\x03\x04\x05\x06\x07\x08", 10},
563 {OPENSSL_U64(0xffffffffffffffff),
564 "\x02\x09\x00\xff\xff\xff\xff\xff\xff\xff\xff", 11},
568 const char *encoding;
570 } ASN1_INVALID_UINT64_TEST;
572 static const ASN1_INVALID_UINT64_TEST kAsn1InvalidUint64Tests[] = {
575 /* Empty contents. */
577 /* Negative number. */
580 {"\x02\x09\x01\x00\x00\x00\x00\x00\x00\x00\x00", 11},
583 static int test_asn1_uint64(void) {
586 for (i = 0; i < sizeof(kAsn1Uint64Tests) / sizeof(kAsn1Uint64Tests[0]); i++) {
587 const ASN1_UINT64_TEST *test = &kAsn1Uint64Tests[i];
594 CBS_init(&cbs, (const uint8_t *)test->encoding, test->encoding_len);
595 if (!CBS_get_asn1_uint64(&cbs, &value) ||
596 CBS_len(&cbs) != 0 ||
597 value != test->value) {
601 if (!CBB_init(&cbb, 0)) {
604 if (!CBB_add_asn1_uint64(&cbb, test->value) ||
605 !CBB_finish(&cbb, &out, &len)) {
609 if (len != test->encoding_len || memcmp(out, test->encoding, len) != 0) {
617 i < sizeof(kAsn1InvalidUint64Tests) / sizeof(kAsn1InvalidUint64Tests[0]);
619 const ASN1_INVALID_UINT64_TEST *test = &kAsn1InvalidUint64Tests[i];
623 CBS_init(&cbs, (const uint8_t *)test->encoding, test->encoding_len);
624 if (CBS_get_asn1_uint64(&cbs, &value)) {
633 CRYPTO_library_init();
637 !test_get_prefixed() ||
638 !test_get_prefixed_bad() ||
642 !test_cbb_finish_child() ||
643 !test_cbb_misuse() ||
644 !test_cbb_prefixed() ||
646 !test_ber_convert() ||
647 !test_asn1_uint64() ||
648 !test_get_optional_asn1_bool()) {