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