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 } else static if (__traits(compiles, { T t = T(); }())) { 179 if (obj is T.init) obj = T(); 180 } 181 (cast()*obj).decodeFrom(this); 182 return this; 183 } 184 185 /* 186 * Request for an object to decode itself 187 */ 188 ref BERDecoder decode(T)(auto ref T obj, ASN1Tag type, ASN1Tag tag) 189 if (__traits(compiles, { obj.decodeFrom(this); }())) 190 { 191 obj.decodeFrom(this); 192 return this; 193 } 194 195 /* 196 * Decode a BER encoded BOOLEAN 197 */ 198 ref BERDecoder decode(ref bool output) 199 { 200 return decode(output, ASN1Tag.BOOLEAN, ASN1Tag.UNIVERSAL); 201 } 202 203 /* 204 * Decode a small BER encoded INTEGER 205 */ 206 ref BERDecoder decode(ref size_t output) 207 { 208 return decode(output, ASN1Tag.INTEGER, ASN1Tag.UNIVERSAL); 209 } 210 211 /* 212 * Decode a BER encoded INTEGER 213 */ 214 ref BERDecoder decode(ref BigInt output) 215 { 216 return decode(output, ASN1Tag.INTEGER, ASN1Tag.UNIVERSAL); 217 } 218 219 220 /* 221 * Decode a BER encoded BOOLEAN 222 */ 223 ref BERDecoder decode(ref bool output, 224 ASN1Tag type_tag, ASN1Tag class_tag = ASN1Tag.CONTEXT_SPECIFIC) 225 { 226 BERObject obj = getNextObject(); 227 obj.assertIsA(type_tag, class_tag); 228 229 if (obj.value.length != 1) 230 throw new BERDecodingError("BER boolean value had invalid size"); 231 232 output = (obj.value[0]) ? true : false; 233 return this; 234 } 235 236 /* 237 * Decode a small BER encoded INTEGER 238 */ 239 ref BERDecoder decode(ref size_t output, 240 ASN1Tag type_tag, ASN1Tag class_tag = ASN1Tag.CONTEXT_SPECIFIC) 241 { 242 BigInt integer; 243 decode(integer, type_tag, class_tag); 244 245 if (integer.bits() > 32) 246 throw new BERDecodingError("Decoded integer value larger than expected"); 247 248 output = 0; 249 foreach (size_t i; 0 .. 4) 250 output = (output << 8) | integer.byteAt(3-i); 251 252 logTrace("decode size_t: ", output); 253 254 return this; 255 } 256 257 /* 258 * Decode a BER encoded INTEGER 259 */ 260 ref BERDecoder decode(ref BigInt output, 261 ASN1Tag type_tag, ASN1Tag class_tag = ASN1Tag.CONTEXT_SPECIFIC) 262 { 263 BERObject obj = getNextObject(); 264 obj.assertIsA(type_tag, class_tag); 265 266 if (obj.value.empty) { 267 output = BigInt("0"); 268 } 269 else 270 { 271 const bool negative = (obj.value[0] & 0x80) ? true : false; 272 273 if (negative) 274 { 275 for (size_t i = obj.value.length; i > 0; --i) 276 if (obj.value[i-1]--) 277 break; 278 foreach (size_t i; 0 .. obj.value.length) 279 obj.value[i] = ~cast(int)obj.value[i]; 280 } 281 output = BigInt(obj.value.ptr, obj.value.length); 282 if (negative) 283 output.flipSign(); 284 } 285 // breaks here 286 logTrace("decode BigInt: ", output.toString()); 287 return this; 288 } 289 290 /* 291 * BER decode a BIT STRING or OCTET STRING 292 */ 293 ref BERDecoder decode(ref SecureVector!ubyte output, ASN1Tag real_type) 294 { 295 return decode(output, real_type, real_type, ASN1Tag.UNIVERSAL); 296 } 297 298 /* 299 * BER decode a BIT STRING or OCTET STRING 300 */ 301 ref BERDecoder decode(ref Vector!ubyte output, ASN1Tag real_type) 302 { 303 return decode(output, real_type, real_type, ASN1Tag.UNIVERSAL); 304 } 305 306 /* 307 * BER decode a BIT STRING or OCTET STRING 308 */ 309 ref BERDecoder decode(ref SecureVector!ubyte buffer, 310 ASN1Tag real_type, 311 ASN1Tag type_tag, ASN1Tag class_tag = ASN1Tag.CONTEXT_SPECIFIC) 312 { 313 if (real_type != ASN1Tag.OCTET_STRING && real_type != ASN1Tag.BIT_STRING) 314 throw new BERBadTag("Bad tag for {BIT,OCTET} STRING", real_type); 315 316 BERObject obj = getNextObject(); 317 obj.assertIsA(type_tag, class_tag); 318 319 if (real_type == ASN1Tag.OCTET_STRING) 320 buffer = obj.value.move; 321 else 322 { 323 if (obj.value.empty()) 324 throw new BERDecodingError("Invalid BIT STRING"); 325 if (obj.value[0] >= 8) 326 throw new BERDecodingError("Bad number of unused bits in BIT STRING"); 327 328 buffer.resize(obj.value.length - 1); 329 copyMem(buffer.ptr, &obj.value[1], obj.value.length - 1); 330 } 331 332 //logTrace("decode SecureVector: ", buffer[]); 333 334 return this; 335 } 336 337 ref BERDecoder decode(ref Vector!ubyte buffer, 338 ASN1Tag real_type, 339 ASN1Tag type_tag, ASN1Tag class_tag = ASN1Tag.CONTEXT_SPECIFIC) 340 { 341 if (real_type != ASN1Tag.OCTET_STRING && real_type != ASN1Tag.BIT_STRING) 342 throw new BERBadTag("Bad tag for {BIT,OCTET} STRING", real_type); 343 344 BERObject obj = getNextObject(); 345 obj.assertIsA(type_tag, class_tag); 346 347 if (real_type == ASN1Tag.OCTET_STRING) 348 buffer = unlock(obj.value); 349 else 350 { 351 if (obj.value.empty()) 352 throw new BERDecodingError("Invalid BIT STRING"); 353 if (obj.value[0] >= 8) 354 throw new BERDecodingError("Bad number of unused bits in BIT STRING"); 355 356 buffer.resize(obj.value.length - 1); 357 copyMem(buffer.ptr, &obj.value[1], obj.value.length - 1); 358 } 359 //logTrace("decode Vector: ", buffer[]); 360 return this; 361 } 362 363 /* 364 * Decode a small BER encoded INTEGER 365 */ 366 ulong decodeConstrainedInteger(ASN1Tag type_tag, 367 ASN1Tag class_tag, 368 size_t T_bytes) 369 { 370 if (T_bytes > 8) 371 throw new BERDecodingError("Can't decode small integer over 8 bytes"); 372 373 BigInt integer; 374 decode(integer, type_tag, class_tag); 375 376 if (integer.bits() > 8*T_bytes) 377 throw new BERDecodingError("Decoded integer value larger than expected"); 378 379 ulong output = 0; 380 foreach (size_t i; 0 .. 8) 381 output = (output << 8) | integer.byteAt(7-i); 382 383 //logTrace("decode Integer: (64bit) ", output); 384 385 return output; 386 } 387 388 ref BERDecoder decodeIntegerType(T)(ref T output) 389 { 390 return decodeIntegerType!T(output, ASN1Tag.INTEGER, ASN1Tag.UNIVERSAL); 391 } 392 393 ref BERDecoder decodeIntegerType(T)(ref T output, 394 ASN1Tag type_tag, 395 ASN1Tag class_tag = ASN1Tag.CONTEXT_SPECIFIC) 396 { 397 output = cast(T) decodeConstrainedInteger(type_tag, class_tag, (output).sizeof); 398 return this; 399 } 400 401 /* 402 * Decode an OPTIONAL or DEFAULT element 403 */ 404 ref BERDecoder decodeOptional(T)(auto ref T output, 405 ASN1Tag type_tag, 406 ASN1Tag class_tag, 407 T default_value = T.init) 408 { 409 BERObject obj = getNextObject(); 410 411 if (obj.type_tag == type_tag && obj.class_tag == class_tag) 412 { 413 if ((class_tag & ASN1Tag.CONSTRUCTED) && (class_tag & ASN1Tag.CONTEXT_SPECIFIC)) 414 BERDecoder(obj.value).decode(output).verifyEnd(); 415 else 416 { 417 pushBack(obj); 418 decode(output, type_tag, class_tag); 419 } 420 } 421 else 422 { 423 static if (__traits(hasMember, T, "isRefCounted")) { 424 if (default_value is T.init) 425 output = T(); 426 else output = default_value; 427 } 428 else 429 output = default_value; 430 pushBack(obj); 431 } 432 433 /* 434 static if (__traits(hasMember, T, "toString")) 435 logTrace("decode Optional ", T.stringof, ": ", output.toString()); 436 else static if (__traits(compiles, { to!string(output); }())) 437 logTrace("decode Optional ", T.stringof, ": ", output.to!string); 438 else 439 logTrace("decode Optional ", T.stringof); 440 */ 441 442 return this; 443 } 444 445 /* 446 * Decode an OPTIONAL or DEFAULT element 447 */ 448 ref BERDecoder decodeOptionalImplicit(T)(ref T output, 449 ASN1Tag type_tag, 450 ASN1Tag class_tag, 451 ASN1Tag real_type, 452 ASN1Tag real_class, 453 T default_value = T.init) 454 { 455 BERObject obj = getNextObject(); 456 457 if (obj.type_tag == type_tag && obj.class_tag == class_tag) 458 { 459 obj.type_tag = real_type; 460 obj.class_tag = real_class; 461 pushBack(obj); 462 decode(output, real_type, real_class); 463 } 464 else 465 { 466 output = default_value; 467 pushBack(obj); 468 } 469 /* 470 static if (__traits(hasMember, T, "toString")) 471 logTrace("decode OptionalImplicit ", T.stringof, ": ", output.toString()); 472 else 473 logTrace("decode OptionalImplicit ", T.stringof); 474 */ 475 return this; 476 } 477 478 479 /* 480 * Decode a list of homogenously typed values 481 */ 482 ref BERDecoder decodeList(T, Alloc)(auto ref Vector!(T, Alloc) vec, 483 ASN1Tag type_tag = ASN1Tag.SEQUENCE, 484 ASN1Tag class_tag = ASN1Tag.UNIVERSAL) 485 { 486 BERDecoder list = startCons(type_tag, class_tag); 487 488 while (list.moreItems()) 489 { 490 T value; 491 list.decode(value); 492 //logTrace("Decode List ", T.stringof); 493 494 vec.pushBack(value); 495 } 496 497 list.endCons(); 498 499 return this; 500 } 501 502 /// ditto 503 ref BERDecoder decodeList(T, Alloc)(auto ref RefCounted!(Vector!(T, Alloc), Alloc) vec, 504 ASN1Tag type_tag = ASN1Tag.SEQUENCE, 505 ASN1Tag class_tag = ASN1Tag.UNIVERSAL) 506 { 507 return decodeList(*vec, type_tag, class_tag); 508 } 509 510 ref BERDecoder decodeAndCheck(T)(in T expected, 511 in string error_msg) 512 { 513 T actual; 514 decode(actual); 515 516 if (actual != expected) 517 throw new DecodingError(error_msg ~ " T " ~ T.stringof ~ " : " ~ actual.to!string ~ ", expected: " ~ expected.to!string); 518 519 static if (__traits(hasMember, T, "toString")) 520 logTrace("decode and check ", T.stringof, ": ", actual.toString()); 521 else 522 logTrace("decode and check ", T.stringof); 523 524 return this; 525 } 526 527 /* 528 * Decode an OPTIONAL string type 529 */ 530 ref BERDecoder decodeOptionalString(Alloc)(ref Vector!( ubyte, Alloc ) output, 531 ASN1Tag real_type, 532 ushort type_no, 533 ASN1Tag class_tag = ASN1Tag.CONTEXT_SPECIFIC) 534 { 535 BERObject obj = getNextObject(); 536 ASN1Tag type_tag = cast(ASN1Tag)(type_no); 537 if (obj.type_tag == type_tag && obj.class_tag == class_tag) 538 { 539 if ((class_tag & ASN1Tag.CONSTRUCTED) && (class_tag & ASN1Tag.CONTEXT_SPECIFIC)) { 540 BERDecoder(obj.value).decode(output, real_type).verifyEnd(); 541 } 542 else 543 { 544 pushBack(obj); 545 decode(output, real_type, type_tag, class_tag); 546 } 547 } 548 else 549 { 550 output.clear(); 551 pushBack(obj); 552 } 553 554 //logTrace("decode optional string ", output[]); 555 556 557 return this; 558 } 559 560 //BERDecoder operator=(in BERDecoder); 561 562 ref BERDecoder decodeOctetStringBigint(ref BigInt output) 563 { 564 SecureVector!ubyte out_vec; 565 decode(out_vec, ASN1Tag.OCTET_STRING); 566 output = BigInt.decode(out_vec.ptr, out_vec.length); 567 //logTrace("decode octet string BigInt (32bit): ", output.getSubstring(0,32)); 568 return this; 569 } 570 571 /* 572 * BERDecoder Constructor 573 */ 574 this(DataSource src) 575 { 576 m_pushed = BERObject.init; 577 m_source = src; 578 m_owns = false; 579 m_pushed.type_tag = m_pushed.class_tag = ASN1Tag.NO_OBJECT; 580 m_parent = null; 581 } 582 583 /* 584 * BERDecoder Constructor 585 */ 586 this(const(ubyte)* data, size_t length) 587 { 588 m_pushed = BERObject.init; 589 m_source = cast(DataSource) DataSourceMemory(data, length); 590 m_owns = true; 591 m_pushed.type_tag = m_pushed.class_tag = ASN1Tag.NO_OBJECT; 592 m_parent = null; 593 } 594 595 /* 596 * BERDecoder Constructor 597 */ 598 this(T, ALLOC)(auto const ref Vector!(T, ALLOC) data) 599 { 600 m_pushed = BERObject.init; 601 m_source = cast(DataSource) DataSourceMemory(data.ptr, data.length); 602 m_owns = true; 603 m_pushed.type_tag = m_pushed.class_tag = ASN1Tag.NO_OBJECT; 604 m_parent = null; 605 } 606 607 /// ditto 608 this(T, ALLOC)(auto const ref RefCounted!(Vector!(T, ALLOC), ALLOC) data) 609 { 610 m_pushed = BERObject.init; 611 m_source = cast(DataSource) DataSourceMemory(data.ptr, data.length); 612 m_owns = true; 613 m_pushed.type_tag = m_pushed.class_tag = ASN1Tag.NO_OBJECT; 614 m_parent = null; 615 } 616 617 this(ref BERDecoder other, BERObject pushed) { 618 m_parent = other.m_parent; 619 m_source = other.m_source; 620 m_pushed = pushed.move(); 621 m_owns = other.m_owns; 622 } 623 624 @property BERDecoder move() { 625 return BERDecoder(this, m_pushed.move()); 626 } 627 628 @property BERDecoder dup() { 629 return BERDecoder(this, m_pushed.dup()); 630 } 631 632 @disable this(this); 633 private: 634 635 BERDecoder* m_parent; 636 DataSource m_source; 637 BERObject m_pushed; 638 bool m_owns; 639 } 640 641 private: 642 /* 643 * BER decode an ASN.1 type tag 644 */ 645 size_t decodeTag(DataSource ber, ref ASN1Tag type_tag, ref ASN1Tag class_tag) 646 { 647 ubyte b; 648 if (!ber.readByte(b)) 649 { 650 type_tag = ASN1Tag.NO_OBJECT; 651 class_tag = ASN1Tag.NO_OBJECT; 652 return 0; 653 } 654 655 if ((b & 0x1F) != 0x1F) 656 { 657 type_tag = cast(ASN1Tag)(b & 0x1F); 658 //logTrace("tag: ", type_tag); 659 class_tag = cast(ASN1Tag)(b & 0xE0); 660 return 1; 661 } 662 663 size_t tag_bytes = 1; 664 class_tag = cast(ASN1Tag)(b & 0xE0); 665 666 size_t tag_buf = 0; 667 while (true) 668 { 669 if (!ber.readByte(b)) 670 throw new BERDecodingError("Long-form tag truncated"); 671 if (tag_buf & 0xFF000000) 672 throw new BERDecodingError("Long-form tag overflowed 32 bits"); 673 ++tag_bytes; 674 tag_buf = (tag_buf << 7) | (b & 0x7F); 675 if ((b & 0x80) == 0) break; 676 } 677 type_tag = cast(ASN1Tag)(tag_buf); 678 return tag_bytes; 679 } 680 681 /* 682 * BER decode an ASN.1 length field 683 */ 684 size_t decodeLength(DataSource ber, ref size_t field_size) 685 { 686 ubyte b; 687 if (!ber.readByte(b)) 688 throw new BERDecodingError("Length field not found"); 689 field_size = 1; 690 if ((b & 0x80) == 0) 691 return b; 692 693 field_size += (b & 0x7F); 694 if (field_size == 1) return findEoc(ber); 695 if (field_size > 5) 696 throw new BERDecodingError("Length field is too large"); 697 698 size_t length = 0; 699 700 foreach (size_t i; 0 .. (field_size - 1)) 701 { 702 if (get_byte(0, length) != 0) 703 throw new BERDecodingError("Field length overflow"); 704 if (!ber.readByte(b)) 705 throw new BERDecodingError("Corrupted length field"); 706 length = (length << 8) | b; 707 } 708 return length; 709 } 710 711 /* 712 * BER decode an ASN.1 length field 713 */ 714 size_t decodeLength(DataSource ber) 715 { 716 size_t dummy; 717 return decodeLength(ber, dummy); 718 } 719 720 /* 721 * Find the EOC marker 722 */ 723 size_t findEoc(DataSource ber) 724 { 725 SecureVector!ubyte buffer = SecureVector!ubyte(DEFAULT_BUFFERSIZE); 726 SecureVector!ubyte data = SecureVector!ubyte(); 727 728 while (true) 729 { 730 const size_t got = ber.peek(buffer.ptr, buffer.length, data.length); 731 if (got == 0) 732 break; 733 734 data ~= buffer[]; 735 } 736 737 auto source = cast(DataSource) DataSourceMemory(&data); 738 size_t length = 0; 739 while (true) 740 { 741 ASN1Tag type_tag, class_tag; 742 size_t tag_size = decodeTag(source, type_tag, class_tag); 743 if (type_tag == ASN1Tag.NO_OBJECT) 744 break; 745 746 size_t length_size = 0; 747 size_t item_size = decodeLength(source, length_size); 748 source.discardNext(item_size); 749 750 length += item_size + length_size + tag_size; 751 752 if (type_tag == ASN1Tag.EOC && class_tag == ASN1Tag.UNIVERSAL) 753 break; 754 } 755 return length; 756 } 757 758