1 /** 2 * BER Decoder 3 * 4 * Copyright: 5 * (C) 1999-2010 Jack Lloyd 6 * (C) 2014-2015 Etienne Cimon 7 * 8 * License: 9 * Botan is released under the Simplified BSD License (see LICENSE.md) 10 */ 11 module botan.asn1.ber_dec; 12 13 import botan.constants; 14 public import botan.asn1.asn1_oid; 15 import botan.filters.data_src; 16 import botan.math.bigint.bigint; 17 import botan.utils.get_byte; 18 import botan.utils.types; 19 20 public: 21 /** 22 * BER Decoding Object 23 */ 24 struct BERDecoder 25 { 26 public: 27 /* 28 * Return the BER encoding of the next object 29 */ 30 BERObject getNextObject() 31 { 32 BERObject next; 33 if (m_pushed.type_tag != ASN1Tag.NO_OBJECT) 34 { 35 next = m_pushed.dup; 36 m_pushed.class_tag = m_pushed.type_tag = ASN1Tag.NO_OBJECT; 37 return next.move(); 38 } 39 decodeTag(m_source, next.type_tag, next.class_tag); 40 41 if (next.type_tag == ASN1Tag.NO_OBJECT) 42 return next.move(); 43 44 size_t length = decodeLength(m_source); 45 //logTrace("length: ", length); 46 47 next.value.resize(length); 48 if (m_source.read(next.value.ptr, length) != length) 49 throw new BERDecodingError("Value truncated"); 50 if (next.type_tag == ASN1Tag.EOC && next.class_tag == ASN1Tag.UNIVERSAL) 51 return getNextObject(); 52 return next.move(); 53 } 54 55 Vector!ubyte getNextOctetString() 56 { 57 Vector!ubyte out_vec; 58 decode(out_vec, ASN1Tag.OCTET_STRING); 59 return out_vec.move(); 60 } 61 62 /* 63 * Push a object back into the stream 64 */ 65 void pushBack()(auto ref BERObject obj) 66 { 67 if (m_pushed.type_tag != ASN1Tag.NO_OBJECT) 68 throw new InvalidState("BERDecoder: Only one push back is allowed"); 69 m_pushed = obj.move(); 70 } 71 72 73 /* 74 * Check if more objects are there 75 */ 76 bool moreItems() const 77 { 78 if (m_source.endOfData() && (m_pushed.type_tag == ASN1Tag.NO_OBJECT)) 79 return false; 80 return true; 81 } 82 83 /* 84 * Verify that no bytes remain in the m_source 85 */ 86 ref BERDecoder verifyEnd() 87 { 88 if (!m_source.endOfData() || (m_pushed.type_tag != ASN1Tag.NO_OBJECT)) 89 throw new InvalidState("verify_end called, but data remains"); 90 return this; 91 } 92 93 /* 94 * Discard all the bytes remaining in the m_source 95 */ 96 ref BERDecoder discardRemaining() 97 { 98 ubyte buf; 99 while (m_source.readByte(buf)) 100 continue; 101 //logTrace("Discarded"); 102 return this; 103 } 104 105 /* 106 * Begin decoding a ASN1Tag.CONSTRUCTED type 107 */ 108 BERDecoder startCons(ASN1Tag type_tag, 109 ASN1Tag class_tag = ASN1Tag.UNIVERSAL) 110 { 111 BERObject obj = getNextObject(); 112 //logTrace("AssertIsA: ", (class_tag | ASN1Tag.CONSTRUCTED)); 113 obj.assertIsA(type_tag, class_tag | ASN1Tag.CONSTRUCTED); 114 115 BERDecoder result = BERDecoder(obj.value.ptr, obj.value.length); 116 result.m_parent = &this; 117 return result.move(); 118 } 119 120 /* 121 * Finish decoding a ASN1Tag.CONSTRUCTED type 122 */ 123 ref BERDecoder endCons() 124 { 125 if (!m_parent) 126 throw new InvalidState("endCons called with NULL m_parent"); 127 if (!m_source.endOfData()) 128 throw new DecodingError("endCons called with data left"); 129 return *m_parent; 130 } 131 132 133 134 ref BERDecoder getNext(ref BERObject ber) 135 { 136 ber = getNextObject(); 137 return this; 138 } 139 140 /* 141 * Save all the bytes remaining in the m_source 142 */ 143 ref BERDecoder rawBytes(T, ALLOC)(ref Vector!(T, ALLOC) output) 144 { 145 output.clear(); 146 ubyte buf; 147 while (m_source.readByte(buf)) 148 output.pushBack(buf); 149 return this; 150 } 151 152 ref BERDecoder rawBytes(T, ALLOC)(ref RefCounted!(Vector!(T, ALLOC), ALLOC) output) 153 { 154 output.clear(); 155 ubyte buf; 156 while (m_source.readByte(buf)) 157 output.pushBack(buf); 158 return this; 159 } 160 161 /* 162 * Decode a BER encoded NULL 163 */ 164 ref BERDecoder decodeNull() 165 { 166 BERObject obj = getNextObject(); 167 obj.assertIsA(ASN1Tag.NULL_TAG, ASN1Tag.UNIVERSAL); 168 if (obj.value.length) 169 throw new BERDecodingError("NULL object had nonzero size"); 170 return this; 171 } 172 173 ref BERDecoder decode(T)(ref T obj) 174 { 175 static if (is(T == class)) { 176 if (!obj) 177 obj = new T(); 178 } 179 else static if (__traits(compiles, { T t = T(); }())) { 180 if (obj is T.init) obj = T(); 181 } 182 //logTrace("Decode obj: ", T.stringof); 183 obj.decodeFrom(this); 184 return this; 185 } 186 187 /* 188 * Request for an object to decode itself 189 */ 190 ref BERDecoder decode(T)(auto ref T obj, ASN1Tag type, ASN1Tag tag) 191 if (__traits(compiles, { obj.decodeFrom(this); }())) 192 { 193 obj.decodeFrom(this); 194 return this; 195 } 196 197 /* 198 * Decode a BER encoded BOOLEAN 199 */ 200 ref BERDecoder decode(ref bool output) 201 { 202 return decode(output, ASN1Tag.BOOLEAN, ASN1Tag.UNIVERSAL); 203 } 204 205 /* 206 * Decode a small BER encoded INTEGER 207 */ 208 ref BERDecoder decode(ref size_t output) 209 { 210 return decode(output, ASN1Tag.INTEGER, ASN1Tag.UNIVERSAL); 211 } 212 213 /* 214 * Decode a BER encoded INTEGER 215 */ 216 ref BERDecoder decode(ref BigInt output) 217 { 218 return decode(output, ASN1Tag.INTEGER, ASN1Tag.UNIVERSAL); 219 } 220 221 222 /* 223 * Decode a BER encoded BOOLEAN 224 */ 225 ref BERDecoder decode(ref bool output, 226 ASN1Tag type_tag, ASN1Tag class_tag = ASN1Tag.CONTEXT_SPECIFIC) 227 { 228 BERObject obj = getNextObject(); 229 obj.assertIsA(type_tag, class_tag); 230 231 if (obj.value.length != 1) 232 throw new BERDecodingError("BER boolean value had invalid size"); 233 234 output = (obj.value[0]) ? true : false; 235 return this; 236 } 237 238 /* 239 * Decode a small BER encoded INTEGER 240 */ 241 ref BERDecoder decode(ref size_t output, 242 ASN1Tag type_tag, ASN1Tag class_tag = ASN1Tag.CONTEXT_SPECIFIC) 243 { 244 BigInt integer; 245 decode(integer, type_tag, class_tag); 246 247 if (integer.bits() > 32) 248 throw new BERDecodingError("Decoded integer value larger than expected"); 249 250 output = 0; 251 foreach (size_t i; 0 .. 4) 252 output = (output << 8) | integer.byteAt(3-i); 253 254 logTrace("decode size_t: ", output); 255 256 return this; 257 } 258 259 /* 260 * Decode a BER encoded INTEGER 261 */ 262 ref BERDecoder decode(ref BigInt output, 263 ASN1Tag type_tag, ASN1Tag class_tag = ASN1Tag.CONTEXT_SPECIFIC) 264 { 265 BERObject obj = getNextObject(); 266 obj.assertIsA(type_tag, class_tag); 267 268 if (obj.value.empty) { 269 output = BigInt("0"); 270 } 271 else 272 { 273 const bool negative = (obj.value[0] & 0x80) ? true : false; 274 275 if (negative) 276 { 277 for (size_t i = obj.value.length; i > 0; --i) 278 if (obj.value[i-1]--) 279 break; 280 foreach (size_t i; 0 .. obj.value.length) 281 obj.value[i] = ~obj.value[i]; 282 } 283 output = BigInt(obj.value.ptr, obj.value.length); 284 if (negative) 285 output.flipSign(); 286 } 287 // breaks here 288 logTrace("decode BigInt: ", output.toString()); 289 return this; 290 } 291 292 /* 293 * BER decode a BIT STRING or OCTET STRING 294 */ 295 ref BERDecoder decode(ref SecureVector!ubyte output, ASN1Tag real_type) 296 { 297 return decode(output, real_type, real_type, ASN1Tag.UNIVERSAL); 298 } 299 300 /* 301 * BER decode a BIT STRING or OCTET STRING 302 */ 303 ref BERDecoder decode(ref Vector!ubyte output, ASN1Tag real_type) 304 { 305 return decode(output, real_type, real_type, ASN1Tag.UNIVERSAL); 306 } 307 308 /* 309 * BER decode a BIT STRING or OCTET STRING 310 */ 311 ref BERDecoder decode(ref SecureVector!ubyte buffer, 312 ASN1Tag real_type, 313 ASN1Tag type_tag, ASN1Tag class_tag = ASN1Tag.CONTEXT_SPECIFIC) 314 { 315 if (real_type != ASN1Tag.OCTET_STRING && real_type != ASN1Tag.BIT_STRING) 316 throw new BERBadTag("Bad tag for {BIT,OCTET} STRING", real_type); 317 318 BERObject obj = getNextObject(); 319 obj.assertIsA(type_tag, class_tag); 320 321 if (real_type == ASN1Tag.OCTET_STRING) 322 buffer = obj.value.move; 323 else 324 { 325 if (obj.value.empty()) 326 throw new BERDecodingError("Invalid BIT STRING"); 327 if (obj.value[0] >= 8) 328 throw new BERDecodingError("Bad number of unused bits in BIT STRING"); 329 330 buffer.resize(obj.value.length - 1); 331 copyMem(buffer.ptr, &obj.value[1], obj.value.length - 1); 332 } 333 334 //logTrace("decode SecureVector: ", buffer[]); 335 336 return this; 337 } 338 339 ref BERDecoder decode(ref Vector!ubyte buffer, 340 ASN1Tag real_type, 341 ASN1Tag type_tag, ASN1Tag class_tag = ASN1Tag.CONTEXT_SPECIFIC) 342 { 343 if (real_type != ASN1Tag.OCTET_STRING && real_type != ASN1Tag.BIT_STRING) 344 throw new BERBadTag("Bad tag for {BIT,OCTET} STRING", real_type); 345 346 BERObject obj = getNextObject(); 347 obj.assertIsA(type_tag, class_tag); 348 349 if (real_type == ASN1Tag.OCTET_STRING) 350 buffer = unlock(obj.value); 351 else 352 { 353 if (obj.value.empty()) 354 throw new BERDecodingError("Invalid BIT STRING"); 355 if (obj.value[0] >= 8) 356 throw new BERDecodingError("Bad number of unused bits in BIT STRING"); 357 358 buffer.resize(obj.value.length - 1); 359 copyMem(buffer.ptr, &obj.value[1], obj.value.length - 1); 360 } 361 //logTrace("decode Vector: ", buffer[]); 362 return this; 363 } 364 365 /* 366 * Decode a small BER encoded INTEGER 367 */ 368 ulong decodeConstrainedInteger(ASN1Tag type_tag, 369 ASN1Tag class_tag, 370 size_t T_bytes) 371 { 372 if (T_bytes > 8) 373 throw new BERDecodingError("Can't decode small integer over 8 bytes"); 374 375 BigInt integer; 376 decode(integer, type_tag, class_tag); 377 378 if (integer.bits() > 8*T_bytes) 379 throw new BERDecodingError("Decoded integer value larger than expected"); 380 381 ulong output = 0; 382 foreach (size_t i; 0 .. 8) 383 output = (output << 8) | integer.byteAt(7-i); 384 385 //logTrace("decode Integer: (64bit) ", output); 386 387 return output; 388 } 389 390 ref BERDecoder decodeIntegerType(T)(ref T output) 391 { 392 return decodeIntegerType!T(output, ASN1Tag.INTEGER, ASN1Tag.UNIVERSAL); 393 } 394 395 ref BERDecoder decodeIntegerType(T)(ref T output, 396 ASN1Tag type_tag, 397 ASN1Tag class_tag = ASN1Tag.CONTEXT_SPECIFIC) 398 { 399 output = cast(T) decodeConstrainedInteger(type_tag, class_tag, (output).sizeof); 400 return this; 401 } 402 403 /* 404 * Decode an OPTIONAL or DEFAULT element 405 */ 406 ref BERDecoder decodeOptional(T)(auto ref T output, 407 ASN1Tag type_tag, 408 ASN1Tag class_tag, 409 T default_value = T.init) 410 { 411 BERObject obj = getNextObject(); 412 413 if (obj.type_tag == type_tag && obj.class_tag == class_tag) 414 { 415 if ((class_tag & ASN1Tag.CONSTRUCTED) && (class_tag & ASN1Tag.CONTEXT_SPECIFIC)) 416 BERDecoder(obj.value).decode(output).verifyEnd(); 417 else 418 { 419 pushBack(obj); 420 decode(output, type_tag, class_tag); 421 } 422 } 423 else 424 { 425 static if (__traits(hasMember, T, "isRefCounted")) { 426 if (default_value is T.init) 427 output = T(); 428 else output = default_value; 429 } 430 else 431 output = default_value; 432 pushBack(obj); 433 } 434 435 /* 436 static if (__traits(hasMember, T, "toString")) 437 logTrace("decode Optional ", T.stringof, ": ", output.toString()); 438 else static if (__traits(compiles, { to!string(output); }())) 439 logTrace("decode Optional ", T.stringof, ": ", output.to!string); 440 else 441 logTrace("decode Optional ", T.stringof); 442 */ 443 444 return this; 445 } 446 447 /* 448 * Decode an OPTIONAL or DEFAULT element 449 */ 450 ref BERDecoder decodeOptionalImplicit(T)(ref T output, 451 ASN1Tag type_tag, 452 ASN1Tag class_tag, 453 ASN1Tag real_type, 454 ASN1Tag real_class, 455 T default_value = T.init) 456 { 457 BERObject obj = getNextObject(); 458 459 if (obj.type_tag == type_tag && obj.class_tag == class_tag) 460 { 461 obj.type_tag = real_type; 462 obj.class_tag = real_class; 463 pushBack(obj); 464 decode(output, real_type, real_class); 465 } 466 else 467 { 468 output = default_value; 469 pushBack(obj); 470 } 471 /* 472 static if (__traits(hasMember, T, "toString")) 473 logTrace("decode OptionalImplicit ", T.stringof, ": ", output.toString()); 474 else 475 logTrace("decode OptionalImplicit ", T.stringof); 476 */ 477 return this; 478 } 479 480 481 /* 482 * Decode a list of homogenously typed values 483 */ 484 ref BERDecoder decodeList(T, Alloc)(auto ref Vector!(T, Alloc) vec, 485 ASN1Tag type_tag = ASN1Tag.SEQUENCE, 486 ASN1Tag class_tag = ASN1Tag.UNIVERSAL) 487 { 488 BERDecoder list = startCons(type_tag, class_tag); 489 490 while (list.moreItems()) 491 { 492 T value; 493 list.decode(value); 494 //logTrace("Decode List ", T.stringof); 495 496 vec.pushBack(value); 497 } 498 499 list.endCons(); 500 501 return this; 502 } 503 504 /// ditto 505 ref BERDecoder decodeList(T, Alloc)(auto ref RefCounted!(Vector!(T, Alloc), Alloc) vec, 506 ASN1Tag type_tag = ASN1Tag.SEQUENCE, 507 ASN1Tag class_tag = ASN1Tag.UNIVERSAL) 508 { 509 return decodeList(*vec, type_tag, class_tag); 510 } 511 512 ref BERDecoder decodeAndCheck(T)(in T expected, 513 in string error_msg) 514 { 515 T actual; 516 decode(actual); 517 518 if (actual != expected) 519 throw new DecodingError(error_msg ~ " T " ~ T.stringof ~ " : " ~ actual.to!string ~ ", expected: " ~ expected.to!string); 520 521 static if (__traits(hasMember, T, "toString")) 522 logTrace("decode and check ", T.stringof, ": ", actual.toString()); 523 else 524 logTrace("decode and check ", T.stringof); 525 526 return this; 527 } 528 529 /* 530 * Decode an OPTIONAL string type 531 */ 532 ref BERDecoder decodeOptionalString(Alloc)(ref Vector!( ubyte, Alloc ) output, 533 ASN1Tag real_type, 534 ushort type_no, 535 ASN1Tag class_tag = ASN1Tag.CONTEXT_SPECIFIC) 536 { 537 BERObject obj = getNextObject(); 538 ASN1Tag type_tag = cast(ASN1Tag)(type_no); 539 if (obj.type_tag == type_tag && obj.class_tag == class_tag) 540 { 541 if ((class_tag & ASN1Tag.CONSTRUCTED) && (class_tag & ASN1Tag.CONTEXT_SPECIFIC)) { 542 BERDecoder(obj.value).decode(output, real_type).verifyEnd(); 543 } 544 else 545 { 546 pushBack(obj); 547 decode(output, real_type, type_tag, class_tag); 548 } 549 } 550 else 551 { 552 output.clear(); 553 pushBack(obj); 554 } 555 556 //logTrace("decode optional string ", output[]); 557 558 559 return this; 560 } 561 562 //BERDecoder operator=(in BERDecoder); 563 564 ref BERDecoder decodeOctetStringBigint(ref BigInt output) 565 { 566 SecureVector!ubyte out_vec; 567 decode(out_vec, ASN1Tag.OCTET_STRING); 568 output = BigInt.decode(out_vec.ptr, out_vec.length); 569 //logTrace("decode octet string BigInt (32bit): ", output.getSubstring(0,32)); 570 return this; 571 } 572 573 /* 574 * BERDecoder Constructor 575 */ 576 this(DataSource src) 577 { 578 m_pushed = BERObject.init; 579 m_source = src; 580 m_owns = false; 581 m_pushed.type_tag = m_pushed.class_tag = ASN1Tag.NO_OBJECT; 582 m_parent = null; 583 } 584 585 /* 586 * BERDecoder Constructor 587 */ 588 this(const(ubyte)* data, size_t length) 589 { 590 m_pushed = BERObject.init; 591 m_source = cast(DataSource)DataSourceMemory(data, length); 592 m_owns = true; 593 m_pushed.type_tag = m_pushed.class_tag = ASN1Tag.NO_OBJECT; 594 m_parent = null; 595 } 596 597 /* 598 * BERDecoder Constructor 599 */ 600 this(T, ALLOC)(auto const ref Vector!(T, ALLOC) data) 601 { 602 m_pushed = BERObject.init; 603 m_source = cast(DataSource) DataSourceMemory(data.ptr, data.length); 604 m_owns = true; 605 m_pushed.type_tag = m_pushed.class_tag = ASN1Tag.NO_OBJECT; 606 m_parent = null; 607 } 608 609 /// ditto 610 this(T, ALLOC)(auto const ref RefCounted!(Vector!(T, ALLOC), ALLOC) data) 611 { 612 m_pushed = BERObject.init; 613 m_source = cast(DataSource) DataSourceMemory(data.ptr, data.length); 614 m_owns = true; 615 m_pushed.type_tag = m_pushed.class_tag = ASN1Tag.NO_OBJECT; 616 m_parent = null; 617 } 618 619 this(ref BERDecoder other, BERObject pushed) { 620 m_parent = other.m_parent; 621 m_source = other.m_source; 622 m_pushed = pushed.move(); 623 m_owns = other.m_owns; 624 } 625 626 @property BERDecoder move() { 627 return BERDecoder(this, m_pushed.move()); 628 } 629 630 @property BERDecoder dup() { 631 return BERDecoder(this, m_pushed.dup()); 632 } 633 634 @disable this(this); 635 private: 636 637 BERDecoder* m_parent; 638 DataSource m_source; 639 BERObject m_pushed; 640 bool m_owns; 641 } 642 643 private: 644 /* 645 * BER decode an ASN.1 type tag 646 */ 647 size_t decodeTag(DataSource ber, ref ASN1Tag type_tag, ref ASN1Tag class_tag) 648 { 649 ubyte b; 650 if (!ber.readByte(b)) 651 { 652 type_tag = ASN1Tag.NO_OBJECT; 653 class_tag = ASN1Tag.NO_OBJECT; 654 return 0; 655 } 656 657 if ((b & 0x1F) != 0x1F) 658 { 659 type_tag = cast(ASN1Tag)(b & 0x1F); 660 //logTrace("tag: ", type_tag); 661 class_tag = cast(ASN1Tag)(b & 0xE0); 662 return 1; 663 } 664 665 size_t tag_bytes = 1; 666 class_tag = cast(ASN1Tag)(b & 0xE0); 667 668 size_t tag_buf = 0; 669 while (true) 670 { 671 if (!ber.readByte(b)) 672 throw new BERDecodingError("Long-form tag truncated"); 673 if (tag_buf & 0xFF000000) 674 throw new BERDecodingError("Long-form tag overflowed 32 bits"); 675 ++tag_bytes; 676 tag_buf = (tag_buf << 7) | (b & 0x7F); 677 if ((b & 0x80) == 0) break; 678 } 679 type_tag = cast(ASN1Tag)(tag_buf); 680 return tag_bytes; 681 } 682 683 /* 684 * BER decode an ASN.1 length field 685 */ 686 size_t decodeLength(DataSource ber, ref size_t field_size) 687 { 688 ubyte b; 689 if (!ber.readByte(b)) 690 throw new BERDecodingError("Length field not found"); 691 field_size = 1; 692 if ((b & 0x80) == 0) 693 return b; 694 695 field_size += (b & 0x7F); 696 if (field_size == 1) return findEoc(ber); 697 if (field_size > 5) 698 throw new BERDecodingError("Length field is too large"); 699 700 size_t length = 0; 701 702 foreach (size_t i; 0 .. (field_size - 1)) 703 { 704 if (get_byte(0, length) != 0) 705 throw new BERDecodingError("Field length overflow"); 706 if (!ber.readByte(b)) 707 throw new BERDecodingError("Corrupted length field"); 708 length = (length << 8) | b; 709 } 710 return length; 711 } 712 713 /* 714 * BER decode an ASN.1 length field 715 */ 716 size_t decodeLength(DataSource ber) 717 { 718 size_t dummy; 719 return decodeLength(ber, dummy); 720 } 721 722 /* 723 * Find the EOC marker 724 */ 725 size_t findEoc(DataSource ber) 726 { 727 SecureVector!ubyte buffer = SecureVector!ubyte(DEFAULT_BUFFERSIZE); 728 SecureVector!ubyte data = SecureVector!ubyte(); 729 730 while (true) 731 { 732 const size_t got = ber.peek(buffer.ptr, buffer.length, data.length); 733 if (got == 0) 734 break; 735 736 data ~= buffer[]; 737 } 738 739 auto source = cast(DataSource) DataSourceMemory(&data); 740 size_t length = 0; 741 while (true) 742 { 743 ASN1Tag type_tag, class_tag; 744 size_t tag_size = decodeTag(source, type_tag, class_tag); 745 if (type_tag == ASN1Tag.NO_OBJECT) 746 break; 747 748 size_t length_size = 0; 749 size_t item_size = decodeLength(source, length_size); 750 source.discardNext(item_size); 751 752 length += item_size + length_size + tag_size; 753 754 if (type_tag == ASN1Tag.EOC && class_tag == ASN1Tag.UNIVERSAL) 755 break; 756 } 757 return length; 758 } 759 760