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 32static 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 45static 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 64static 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 86static 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 110static 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 233static 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 268static 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 295static 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 322static 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 340static 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 373static 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 422static 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 464static 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 542static 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 575static 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 623struct ASN1Uint64Test { 624 uint64_t value; 625 const char *encoding; 626 size_t encoding_len; 627}; 628 629static 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 641struct ASN1InvalidUint64Test { 642 const char *encoding; 643 size_t encoding_len; 644}; 645 646static 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 659static 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 706static 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 714static 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 734int 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