001 /* 002 * CDDL HEADER START 003 * 004 * The contents of this file are subject to the terms of the 005 * Common Development and Distribution License, Version 1.0 only 006 * (the "License"). You may not use this file except in compliance 007 * with the License. 008 * 009 * You can obtain a copy of the license at 010 * trunk/opends/resource/legal-notices/OpenDS.LICENSE 011 * or https://OpenDS.dev.java.net/OpenDS.LICENSE. 012 * See the License for the specific language governing permissions 013 * and limitations under the License. 014 * 015 * When distributing Covered Code, include this CDDL HEADER in each 016 * file and include the License file at 017 * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable, 018 * add the following below this CDDL HEADER, with the fields enclosed 019 * by brackets "[]" replaced with your own identifying information: 020 * Portions Copyright [yyyy] [name of copyright owner] 021 * 022 * CDDL HEADER END 023 * 024 * 025 * Copyright 2006-2008 Sun Microsystems, Inc. 026 */ 027 package org.opends.server.protocols.asn1; 028 import org.opends.messages.Message; 029 030 031 032 import java.io.Serializable; 033 import java.util.ArrayList; 034 import java.util.Arrays; 035 036 import org.opends.server.api.ProtocolElement; 037 import org.opends.server.types.ByteString; 038 039 import static org.opends.messages.ProtocolMessages.*; 040 import static org.opends.server.protocols.asn1.ASN1Constants.*; 041 import static org.opends.server.util.ServerConstants.*; 042 import static org.opends.server.util.StaticUtils.*; 043 044 045 046 /** 047 * This class defines the data structures and methods to use when interacting 048 * with generic ASN.1 elements. Subclasses may provide more specific 049 * functionality for individual element types. 050 */ 051 @org.opends.server.types.PublicAPI( 052 stability=org.opends.server.types.StabilityLevel.UNCOMMITTED, 053 mayInstantiate=true, 054 mayExtend=false, 055 mayInvoke=true) 056 public class ASN1Element 057 implements ProtocolElement, Serializable 058 { 059 /** 060 * The serial version identifier required to satisfy the compiler because this 061 * class implements the <CODE>java.io.Serializable</CODE> interface. This 062 * value was generated using the <CODE>serialver</CODE> command-line utility 063 * included with the Java SDK. 064 */ 065 private static final long serialVersionUID = -6085322427222358963L; 066 067 068 069 // The BER type for this element. 070 private byte type; 071 072 // The encoded value for this element. 073 private byte[] value; 074 075 076 077 /** 078 * Creates a new ASN.1 element with the specified type and no value. 079 * 080 * @param type The BER type for this ASN.1 element. 081 */ 082 public ASN1Element(byte type) 083 { 084 this.type = type; 085 this.value = NO_VALUE; 086 } 087 088 089 090 /** 091 * Creates a new ASN.1 element with the specified type and value. 092 * 093 * @param type The BER type for this ASN.1 element. 094 * @param value The encoded value for this ASN.1 element. 095 */ 096 public ASN1Element(byte type, byte[] value) 097 { 098 this.type = type; 099 100 if (value == null) 101 { 102 this.value = NO_VALUE; 103 } 104 else 105 { 106 this.value = value; 107 } 108 } 109 110 111 112 /** 113 * Retrieves the BER type for this ASN.1 element. 114 * 115 * @return The BER type for this ASN.1 element. 116 */ 117 public final byte getType() 118 { 119 return type; 120 } 121 122 123 124 /** 125 * Specifies the BER type for this ASN.1 element. 126 * 127 * @param type The BER type for this ASN.1 element. 128 */ 129 public final void setType(byte type) 130 { 131 this.type = type; 132 } 133 134 135 136 /** 137 * Indicates whether this ASN.1 element is in the universal class. 138 * 139 * @return <CODE>true</CODE> if this ASN.1 element is in the universal class, 140 * or <CODE>false</CODE> if not. 141 */ 142 public final boolean isUniversal() 143 { 144 return ((type & TYPE_MASK_ALL_BUT_CLASS) == TYPE_MASK_UNIVERSAL); 145 } 146 147 148 149 /** 150 * Indicates whether this ASN.1 element is in the application-specific class. 151 * 152 * @return <CODE>true</CODE> if this ASN.1 element is in the 153 * application-specific class, or <CODE>false</CODE> if not. 154 */ 155 public final boolean isApplicationSpecific() 156 { 157 return ((type & TYPE_MASK_ALL_BUT_CLASS) == TYPE_MASK_APPLICATION); 158 } 159 160 161 162 /** 163 * Indicates whether this ASN.1 element is in the context-specific class. 164 * 165 * @return <CODE>true</CODE> if this ASN.1 element is in the context-specific 166 * class, or <CODE>false</CODE> if not. 167 */ 168 public final boolean isContextSpecific() 169 { 170 return ((type & TYPE_MASK_ALL_BUT_CLASS) == TYPE_MASK_CONTEXT); 171 } 172 173 174 175 /** 176 * Indicates whether this ASN.1 element is in the private class. 177 * 178 * @return <CODE>true</CODE> if this ASN.1 element is in the private class, 179 * or <CODE>false</CODE> if not. 180 */ 181 public final boolean isPrivate() 182 { 183 return ((type & TYPE_MASK_ALL_BUT_CLASS) == TYPE_MASK_PRIVATE); 184 } 185 186 187 188 /** 189 * Indicates whether this ASN.1 element has a primitive value. 190 * 191 * @return <CODE>true</CODE> if this ASN.1 element has a primitive value, or 192 * <CODE>false</CODE> if it is constructed. 193 */ 194 public final boolean isPrimitive() 195 { 196 return ((type & TYPE_MASK_ALL_BUT_PC) == TYPE_MASK_PRIMITIVE); 197 } 198 199 200 201 /** 202 * Indicates whether this ASN.1 element has a constructed value. 203 * 204 * @return <CODE>true</CODE> if this ASN.1 element has a constructed value, 205 * or <CODE>false</CODE> if it is primitive. 206 */ 207 public final boolean isConstructed() 208 { 209 return ((type & TYPE_MASK_ALL_BUT_PC) == TYPE_MASK_CONSTRUCTED); 210 } 211 212 213 214 /** 215 * Retrieves the encoded value for this ASN.1 element. 216 * 217 * @return The encoded value for this ASN.1 element. 218 */ 219 public final byte[] value() 220 { 221 return value; 222 } 223 224 225 226 /** 227 * Specifies the encoded value for this ASN.1 element. 228 * 229 * @param value The encoded value for this ASN.1 element. 230 * 231 * @throws ASN1Exception If the provided value is not appropriate for this 232 * type of ASN.1 element. 233 */ 234 public void setValue(byte[] value) 235 throws ASN1Exception 236 { 237 if (value == null) 238 { 239 this.value = NO_VALUE; 240 } 241 else 242 { 243 this.value = value; 244 } 245 } 246 247 248 249 /** 250 * Specifies the value to use for this ASN.1 element, but without performing 251 * any validity checks. This should only be used by subclasses and they must 252 * ensure that it is non-null and conforms to the appropriate requirements of 253 * the underlying type. 254 * 255 * @param value The encoded value for this ASN.1 element. 256 */ 257 protected final void setValueInternal(byte[] value) 258 { 259 this.value = value; 260 } 261 262 263 264 /** 265 * Encodes the provided value for use as the length of an ASN.1 element. 266 * 267 * @param length The length to encode for use in an ASN.1 element. 268 * 269 * @return The byte array containing the encoded length. 270 */ 271 public static byte[] encodeLength(int length) 272 { 273 if (length < 128) 274 { 275 return new byte[] { (byte) length }; 276 } 277 278 if ((length & 0x000000FF) == length) 279 { 280 return new byte[] 281 { 282 (byte) 0x81, 283 (byte) (length & 0xFF) 284 }; 285 } 286 else if ((length & 0x0000FFFF) == length) 287 { 288 return new byte[] 289 { 290 (byte) 0x82, 291 (byte) ((length >> 8) & 0xFF), 292 (byte) (length & 0xFF) 293 }; 294 } 295 else if ((length & 0x00FFFFFF) == length) 296 { 297 return new byte[] 298 { 299 (byte) 0x83, 300 (byte) ((length >> 16) & 0xFF), 301 (byte) ((length >> 8) & 0xFF), 302 (byte) (length & 0xFF) 303 }; 304 } 305 else 306 { 307 return new byte[] 308 { 309 (byte) 0x84, 310 (byte) ((length >> 24) & 0xFF), 311 (byte) ((length >> 16) & 0xFF), 312 (byte) ((length >> 8) & 0xFF), 313 (byte) (length & 0xFF) 314 }; 315 } 316 } 317 318 319 320 /** 321 * Encodes this ASN.1 element to a byte array. 322 * 323 * @return The byte array containing the encoded ASN.1 element. 324 */ 325 public final byte[] encode() 326 { 327 if (value.length == 0) 328 { 329 return new byte[] { type, 0x00 }; 330 } 331 else if (value.length < 128) 332 { 333 byte[] encodedElement = new byte[value.length + 2]; 334 335 encodedElement[0] = type; 336 encodedElement[1] = (byte) value.length; 337 System.arraycopy(value, 0, encodedElement, 2, value.length); 338 339 return encodedElement; 340 } 341 else 342 { 343 byte[] encodedLength = encodeLength(value.length); 344 byte[] encodedElement = new byte[1 + value.length + encodedLength.length]; 345 346 encodedElement[0] = type; 347 System.arraycopy(encodedLength, 0, encodedElement, 1, 348 encodedLength.length); 349 System.arraycopy(value, 0, encodedElement, 1+encodedLength.length, 350 value.length); 351 352 return encodedElement; 353 } 354 } 355 356 357 358 /** 359 * Retrieves a byte array containing the encoded representation of the 360 * provided boolean value. 361 * 362 * @param booleanValue The boolean value to encode. 363 * 364 * @return A byte array containing the encoded representation of the provided 365 * boolean value. 366 */ 367 public static byte[] encodeValue(boolean booleanValue) 368 { 369 return (booleanValue ? BOOLEAN_VALUE_TRUE : BOOLEAN_VALUE_FALSE); 370 } 371 372 373 374 /** 375 * Retrieves a byte array containing the encoded representation of the 376 * provided integer value. 377 * 378 * @param intValue The integer value to encode. 379 * 380 * @return A byte array containing the encoded representation of the provided 381 * integer value. 382 */ 383 public static byte[] encodeValue(int intValue) 384 { 385 if ((intValue & 0x0000007F) == intValue) 386 { 387 return new byte[] 388 { 389 (byte) (intValue & 0xFF) 390 }; 391 } 392 else if ((intValue & 0x00007FFF) == intValue) 393 { 394 return new byte[] 395 { 396 (byte) ((intValue >> 8) & 0xFF), 397 (byte) (intValue & 0xFF) 398 }; 399 } 400 else if ((intValue & 0x007FFFFF) == intValue) 401 { 402 return new byte[] 403 { 404 (byte) ((intValue >> 16) & 0xFF), 405 (byte) ((intValue >> 8) & 0xFF), 406 (byte) (intValue & 0xFF) 407 }; 408 } 409 else 410 { 411 return new byte[] 412 { 413 (byte) ((intValue >> 24) & 0xFF), 414 (byte) ((intValue >> 16) & 0xFF), 415 (byte) ((intValue >> 8) & 0xFF), 416 (byte) (intValue & 0xFF) 417 }; 418 } 419 } 420 421 422 423 /** 424 * Retrieves a byte array containing the encoded representation of the 425 * provided long value. 426 * 427 * @param longValue The long value to encode. 428 * 429 * @return A byte array containing the encoded representation of the provided 430 * long value. 431 */ 432 public static byte[] encodeLongValue(long longValue) 433 { 434 if ((longValue & 0x000000000000007FL) == longValue) 435 { 436 return new byte[] 437 { 438 (byte) (longValue & 0xFF) 439 }; 440 } 441 else if ((longValue & 0x0000000000007FFFL) == longValue) 442 { 443 return new byte[] 444 { 445 (byte) ((longValue >> 8) & 0xFF), 446 (byte) (longValue & 0xFF) 447 }; 448 } 449 else if ((longValue & 0x00000000007FFFFFL) == longValue) 450 { 451 return new byte[] 452 { 453 (byte) ((longValue >> 16) & 0xFF), 454 (byte) ((longValue >> 8) & 0xFF), 455 (byte) (longValue & 0xFF) 456 }; 457 } 458 else if ((longValue & 0x000000007FFFFFFFL) == longValue) 459 { 460 return new byte[] 461 { 462 (byte) ((longValue >> 24) & 0xFF), 463 (byte) ((longValue >> 16) & 0xFF), 464 (byte) ((longValue >> 8) & 0xFF), 465 (byte) (longValue & 0xFF) 466 }; 467 } 468 else if ((longValue & 0x0000007FFFFFFFFFL) == longValue) 469 { 470 return new byte[] 471 { 472 (byte) ((longValue >> 32) & 0xFF), 473 (byte) ((longValue >> 24) & 0xFF), 474 (byte) ((longValue >> 16) & 0xFF), 475 (byte) ((longValue >> 8) & 0xFF), 476 (byte) (longValue & 0xFF) 477 }; 478 } 479 else if ((longValue & 0x00007FFFFFFFFFFFL) == longValue) 480 { 481 return new byte[] 482 { 483 (byte) ((longValue >> 40) & 0xFF), 484 (byte) ((longValue >> 32) & 0xFF), 485 (byte) ((longValue >> 24) & 0xFF), 486 (byte) ((longValue >> 16) & 0xFF), 487 (byte) ((longValue >> 8) & 0xFF), 488 (byte) (longValue & 0xFF) 489 }; 490 } 491 else if ((longValue & 0x007FFFFFFFFFFFFFL) == longValue) 492 { 493 return new byte[] 494 { 495 (byte) ((longValue >> 48) & 0xFF), 496 (byte) ((longValue >> 40) & 0xFF), 497 (byte) ((longValue >> 32) & 0xFF), 498 (byte) ((longValue >> 24) & 0xFF), 499 (byte) ((longValue >> 16) & 0xFF), 500 (byte) ((longValue >> 8) & 0xFF), 501 (byte) (longValue & 0xFF) 502 }; 503 } 504 else 505 { 506 return new byte[] 507 { 508 (byte) ((longValue >> 56) & 0xFF), 509 (byte) ((longValue >> 48) & 0xFF), 510 (byte) ((longValue >> 40) & 0xFF), 511 (byte) ((longValue >> 32) & 0xFF), 512 (byte) ((longValue >> 24) & 0xFF), 513 (byte) ((longValue >> 16) & 0xFF), 514 (byte) ((longValue >> 8) & 0xFF), 515 (byte) (longValue & 0xFF) 516 }; 517 } 518 } 519 520 521 522 /** 523 * Retrieves a byte array containing the encoded representation of the 524 * provided set of ASN.1 elements. 525 * 526 * @param elements The set of ASN.1 elements to encode into the value. 527 * 528 * @return A byte array containing the encoded representation of the 529 * provided set of ASN.1 elements. 530 */ 531 public static byte[] encodeValue(ArrayList<ASN1Element> elements) 532 { 533 if (elements == null) 534 { 535 return NO_VALUE; 536 } 537 538 539 int totalLength = 0; 540 byte[][] encodedElements = new byte[elements.size()][]; 541 for (int i=0; i < encodedElements.length; i++) 542 { 543 encodedElements[i] = elements.get(i).encode(); 544 totalLength += encodedElements[i].length; 545 } 546 547 byte[] encodedValue = new byte[totalLength]; 548 int startPos = 0; 549 for (byte[] b : encodedElements) 550 { 551 System.arraycopy(b, 0, encodedValue, startPos, b.length); 552 startPos += b.length; 553 } 554 555 return encodedValue; 556 } 557 558 559 560 /** 561 * Decodes the contents of the provided byte array as an ASN.1 element. 562 * 563 * @param encodedElement The byte array containing the ASN.1 element to 564 * decode. 565 * 566 * @return The decoded ASN.1 element. 567 * 568 * @throws ASN1Exception If a problem occurs while attempting to decode the 569 * byte array as an ASN.1 element. 570 */ 571 public static ASN1Element decode(byte[] encodedElement) 572 throws ASN1Exception 573 { 574 // First make sure that the array is not null and long enough to contain 575 // a valid ASN.1 element. 576 if (encodedElement == null) 577 { 578 Message message = ERR_ASN1_NULL_ELEMENT.get(); 579 throw new ASN1Exception(message); 580 } 581 else if (encodedElement.length < 2) 582 { 583 Message message = ERR_ASN1_SHORT_ELEMENT.get(encodedElement.length); 584 throw new ASN1Exception(message); 585 } 586 587 588 // Next, decode the length. This allows multi-byte lengths with up to four 589 // bytes used to indicate how many bytes are in the length. 590 byte type = encodedElement[0]; 591 int length = (encodedElement[1] & 0x7F); 592 int valueStartPos = 2; 593 if (length != encodedElement[1]) 594 { 595 int numLengthBytes = length; 596 if (numLengthBytes > 4) 597 { 598 Message message = ERR_ASN1_INVALID_NUM_LENGTH_BYTES.get(numLengthBytes); 599 throw new ASN1Exception(message); 600 } 601 else if (encodedElement.length < (2 + numLengthBytes)) 602 { 603 Message message = ERR_ASN1_TRUNCATED_LENGTH.get(numLengthBytes); 604 throw new ASN1Exception(message); 605 } 606 607 length = 0x00; 608 valueStartPos = 2 + numLengthBytes; 609 for (int i=0; i < numLengthBytes; i++) 610 { 611 length = (length << 8) | (encodedElement[i+2] & 0xFF); 612 } 613 } 614 615 616 // Make sure that the number of bytes left is equal to the number of bytes 617 // in the value. 618 if ((encodedElement.length - valueStartPos) != length) 619 { 620 Message message = ERR_ASN1_LENGTH_MISMATCH.get( 621 length, (encodedElement.length - valueStartPos)); 622 throw new ASN1Exception(message); 623 } 624 625 626 // Copy the value and construct the element to return. 627 byte[] value = new byte[length]; 628 System.arraycopy(encodedElement, valueStartPos, value, 0, length); 629 return new ASN1Element(type, value); 630 } 631 632 633 634 /** 635 * Decodes the specified portion of the provided byte array as an ASN.1 636 * element. 637 * 638 * @param encodedElement The byte array containing the ASN.1 element to 639 * decode. 640 * @param startPos The position in the provided array at which to 641 * start decoding. 642 * @param length The number of bytes in the set of data to decode as 643 * an ASN.1 element. 644 * 645 * @return The decoded ASN.1 element. 646 * 647 * @throws ASN1Exception If a problem occurs while attempting to decode the 648 * byte array as an ASN.1 element. 649 */ 650 public static ASN1Element decode(byte[] encodedElement, int startPos, 651 int length) 652 throws ASN1Exception 653 { 654 // First make sure that the array is not null and long enough to contain 655 // a valid ASN.1 element. 656 if (encodedElement == null) 657 { 658 Message message = ERR_ASN1_NULL_ELEMENT.get(); 659 throw new ASN1Exception(message); 660 } 661 else if ((startPos < 0) || (startPos+length > encodedElement.length) || 662 (length < 2)) 663 { 664 Message message = ERR_ASN1_SHORT_ELEMENT.get(encodedElement.length); 665 throw new ASN1Exception(message); 666 } 667 668 669 // Next, decode the length. This allows multi-byte lengths with up to four 670 // bytes used to indicate how many bytes are in the length. 671 byte type = encodedElement[startPos]; 672 int elementLength = (encodedElement[startPos+1] & 0x7F); 673 int valueStartPos = startPos + 2; 674 if (elementLength != encodedElement[startPos+1]) 675 { 676 int numLengthBytes = elementLength; 677 if (numLengthBytes > 4) 678 { 679 Message message = ERR_ASN1_INVALID_NUM_LENGTH_BYTES.get(numLengthBytes); 680 throw new ASN1Exception(message); 681 } 682 else if (startPos+length < (2 + numLengthBytes)) 683 { 684 Message message = ERR_ASN1_TRUNCATED_LENGTH.get(numLengthBytes); 685 throw new ASN1Exception(message); 686 } 687 688 elementLength = 0x00; 689 valueStartPos = startPos + 2 + numLengthBytes; 690 for (int i=0; i < numLengthBytes; i++) 691 { 692 elementLength = (elementLength << 8) | (encodedElement[i+2] & 0xFF); 693 } 694 } 695 696 697 // Make sure that the number of bytes left is equal to the number of bytes 698 // in the value. 699 if ((startPos+length - valueStartPos) != elementLength) 700 { 701 Message message = ERR_ASN1_LENGTH_MISMATCH.get( 702 elementLength, (startPos+length - valueStartPos)); 703 throw new ASN1Exception(message); 704 } 705 706 707 // Copy the value and construct the element to return. 708 byte[] value = new byte[elementLength]; 709 System.arraycopy(encodedElement, valueStartPos, value, 0, elementLength); 710 return new ASN1Element(type, value); 711 } 712 713 714 715 /** 716 * Decodes this ASN.1 element as an ASN.1 Boolean element. 717 * 718 * @return The ASN.1 Boolean element decoded from this element. 719 * 720 * @throws ASN1Exception If a problem occurs while attempting to decode this 721 * element as an ASN.1 Boolean element. 722 */ 723 public final ASN1Boolean decodeAsBoolean() 724 throws ASN1Exception 725 { 726 return ASN1Boolean.decodeAsBoolean(this); 727 } 728 729 730 731 /** 732 * Decodes this ASN.1 element as an ASN.1 enumerated element. 733 * 734 * @return The ASN.1 enumerated element decoded from this element. 735 * 736 * @throws ASN1Exception If a problem occurs while attempting to decode this 737 * element as an ASN.1 enumerated element. 738 */ 739 public final ASN1Enumerated decodeAsEnumerated() 740 throws ASN1Exception 741 { 742 return ASN1Enumerated.decodeAsEnumerated(this); 743 } 744 745 746 747 /** 748 * Decodes this ASN.1 element as an ASN.1 integer element. 749 * 750 * @return The ASN.1 integer element decoded from this element. 751 * 752 * @throws ASN1Exception If a problem occurs while attempting to decode this 753 * element as an ASN.1 integer element. 754 */ 755 public final ASN1Integer decodeAsInteger() 756 throws ASN1Exception 757 { 758 return ASN1Integer.decodeAsInteger(this); 759 } 760 761 762 763 /** 764 * Decodes this ASN.1 element as an ASN.1 long element. 765 * 766 * @return The ASN.1 long element decoded from this element. 767 * 768 * @throws ASN1Exception If a problem occurs while attempting to decode this 769 * element as an ASN.1 long element. 770 */ 771 public final ASN1Long decodeAsLong() 772 throws ASN1Exception 773 { 774 return ASN1Long.decodeAsLong(this); 775 } 776 777 778 779 /** 780 * Decodes this ASN.1 element as an ASN.1 null element. 781 * 782 * @return The ASN.1 null element decoded from this element. 783 * 784 * @throws ASN1Exception If a problem occurs while attempting to decode this 785 * element as an ASN.1 null element. 786 */ 787 public final ASN1Null decodeAsNull() 788 throws ASN1Exception 789 { 790 return ASN1Null.decodeAsNull(this); 791 } 792 793 794 795 /** 796 * Decodes this ASN.1 element as an ASN.1 octet string element. 797 * 798 * @return The ASN.1 octet string element decoded from this element. 799 * 800 * @throws ASN1Exception If a problem occurs while attempting to decode this 801 * element as an ASN.1 octet string element. 802 */ 803 public final ASN1OctetString decodeAsOctetString() 804 throws ASN1Exception 805 { 806 return ASN1OctetString.decodeAsOctetString(this); 807 } 808 809 810 811 /** 812 * Decodes this ASN.1 element as an ASN.1 sequence element. 813 * 814 * @return The ASN.1 sequence element decoded from this element. 815 * 816 * @throws ASN1Exception If a problem occurs while attempting to decode this 817 * element as an ASN.1 sequence element. 818 */ 819 public final ASN1Sequence decodeAsSequence() 820 throws ASN1Exception 821 { 822 return ASN1Sequence.decodeAsSequence(this); 823 } 824 825 826 827 /** 828 * Decodes this ASN.1 element as an ASN.1 set element. 829 * 830 * @return The ASN.1 set element decoded from this element. 831 * 832 * @throws ASN1Exception If a problem occurs while attempting to decode this 833 * element as an ASN.1 set element. 834 */ 835 public final ASN1Set decodeAsSet() 836 throws ASN1Exception 837 { 838 return ASN1Set.decodeAsSet(this); 839 } 840 841 842 843 /** 844 * Decodes the provided byte array as a collection of ASN.1 elements as would 845 * be found in the value of a sequence or set. 846 * 847 * @param encodedElements The byte array containing the data to decode. 848 * 849 * @return The set of decoded ASN.1 elements. 850 * 851 * @throws ASN1Exception If a problem occurs while attempting to decode the 852 * set of ASN.1 elements from the provided byte array. 853 */ 854 public static ArrayList<ASN1Element> decodeElements(byte[] encodedElements) 855 throws ASN1Exception 856 { 857 // Make sure that the element array is not null. 858 if (encodedElements == null) 859 { 860 Message message = ERR_ASN1_ELEMENT_SET_NULL.get(); 861 throw new ASN1Exception(message); 862 } 863 864 865 // Iterate through the array and keep reading elements until the end is 866 // reached. 867 ArrayList<ASN1Element> elements = new ArrayList<ASN1Element>(); 868 int startPos = 0; 869 while (startPos < encodedElements.length) 870 { 871 byte type = encodedElements[startPos++]; 872 if (startPos >= encodedElements.length) 873 { 874 Message message = ERR_ASN1_ELEMENT_SET_NO_LENGTH.get(); 875 throw new ASN1Exception(message); 876 } 877 878 879 byte firstLengthByte = encodedElements[startPos++]; 880 int length = (byte) (firstLengthByte & 0x7F); 881 if (length != firstLengthByte) 882 { 883 int numLengthBytes = length; 884 if (numLengthBytes > 4) 885 { 886 Message message = 887 ERR_ASN1_ELEMENT_SET_INVALID_NUM_LENGTH_BYTES.get(numLengthBytes); 888 throw new ASN1Exception(message); 889 } 890 891 if (numLengthBytes > encodedElements.length - startPos) 892 { 893 Message message = 894 ERR_ASN1_ELEMENT_SET_TRUNCATED_LENGTH.get(numLengthBytes); 895 throw new ASN1Exception(message); 896 } 897 898 length = 0x00; 899 for (int i=0; i < numLengthBytes; i++) 900 { 901 length = (length << 8) | (encodedElements[startPos++] & 0xFF); 902 } 903 } 904 905 906 // Make sure that there are at least enough bytes to hold the value. 907 if (length > encodedElements.length - startPos) 908 { 909 Message message = ERR_ASN1_ELEMENT_SET_TRUNCATED_VALUE.get( 910 length, (encodedElements.length-startPos)); 911 throw new ASN1Exception(message); 912 } 913 914 915 // Create the element and add it to the list. 916 byte[] value = new byte[length]; 917 System.arraycopy(encodedElements, startPos, value, 0, length); 918 elements.add(new ASN1Element(type, value)); 919 startPos += length; 920 } 921 922 923 return elements; 924 } 925 926 927 928 /** 929 * Retrieves the name of the protocol associated with this protocol element. 930 * 931 * @return The name of the protocol associated with this protocol element. 932 */ 933 public final String getProtocolElementName() 934 { 935 return "ASN.1"; 936 } 937 938 939 940 /** 941 * Indicates whether the provided object is equal to this ASN.1 element. 942 * 943 * @param o The object for which to make the determination. 944 * 945 * @return <CODE>true</CODE> if the provided object is an ASN.1 element that 946 * is equal to this element, or <CODE>false</CODE> if not. The 947 * object will be considered equal if it is an ASN.1 element (or a 948 * subclass) with the same type and encoded value. 949 */ 950 public final boolean equals(Object o) 951 { 952 if (this == o) 953 { 954 return true; 955 } 956 957 if ((o == null) || (! (o instanceof ASN1Element))) 958 { 959 return false; 960 } 961 962 ASN1Element e = (ASN1Element) o; 963 return ((type == e.type) && Arrays.equals(value, e.value)); 964 } 965 966 967 968 /** 969 * Indicates whether the provided ASN.1 element has a value that is equal to 970 * the value of this ASN.1 element. 971 * 972 * @param element The ASN.1 element whose value should be compared against 973 * the value of this element. 974 * 975 * @return <CODE>true</CODE> if the values of the elements are equal, or 976 * <CODE>false</CODE> if not. 977 */ 978 public final boolean equalsIgnoreType(ASN1Element element) 979 { 980 return Arrays.equals(value, element.value); 981 } 982 983 984 985 /** 986 * Indicates whether the provided byte string has a value that is equal to 987 * the value of this ASN.1 element. 988 * 989 * @param byteString The byte string whose value should be compared against 990 * the value of this element. 991 * 992 * @return <CODE>true</CODE> if the values are equal, or <CODE>false</CODE> 993 * if not. 994 */ 995 public final boolean equalsIgnoreType(ByteString byteString) 996 { 997 return Arrays.equals(value, byteString.value()); 998 } 999 1000 1001 1002 /** 1003 * Indicates whether the provided ASN.1 element is equal to this element. 1004 * 1005 * @param e The ASN.1 element for which to make the determination. 1006 * 1007 * @return <CODE>true</CODE> ASN.1 element is equal to this element, 1008 * or <CODE>false</CODE> if not. The elements will be considered 1009 * equal if they have the same type and encoded value. 1010 */ 1011 public final boolean equalsElement(ASN1Element e) 1012 { 1013 if (this == e) 1014 { 1015 return true; 1016 } 1017 1018 if (e == null) 1019 { 1020 return false; 1021 } 1022 1023 return ((type == e.type) && Arrays.equals(value, e.value)); 1024 } 1025 1026 1027 1028 /** 1029 * Retrieves the hash code for this ASN.1 element. It will be constructed 1030 * from the sum of the type and up to the first twenty bytes of the value. 1031 * 1032 * @return The hash code for this ASN.1 element. 1033 */ 1034 public final int hashCode() 1035 { 1036 int hashCode = type; 1037 int length = Math.min(20, value.length); 1038 for (int i=0; i < length; i++) 1039 { 1040 hashCode += value[i]; 1041 } 1042 1043 return hashCode; 1044 } 1045 1046 1047 1048 /** 1049 * Retrieves a string representation of this ASN.1 element. 1050 * 1051 * @return A string representation of this ASN.1 element. 1052 */ 1053 public final String toString() 1054 { 1055 StringBuilder buffer = new StringBuilder(); 1056 toString(buffer); 1057 return buffer.toString(); 1058 } 1059 1060 1061 1062 /** 1063 * Appends a string representation of this ASN.1 element to the provided 1064 * buffer. 1065 * 1066 * @param buffer The buffer to which the information should be appended. 1067 */ 1068 public void toString(StringBuilder buffer) 1069 { 1070 buffer.append("ASN1Element(type="); 1071 buffer.append(byteToHex(type)); 1072 buffer.append(", length="); 1073 buffer.append(value.length); 1074 buffer.append(")"); 1075 } 1076 1077 1078 1079 /** 1080 * Appends a string representation of this protocol element to the provided 1081 * buffer. 1082 * 1083 * @param buffer The buffer into which the string representation should be 1084 * written. 1085 * @param indent The number of spaces that should be used to indent the 1086 * resulting string representation. 1087 */ 1088 public void toString(StringBuilder buffer, int indent) 1089 { 1090 StringBuilder indentBuf = new StringBuilder(indent); 1091 for (int i=0 ; i < indent; i++) 1092 { 1093 indentBuf.append(' '); 1094 } 1095 1096 buffer.append(indentBuf); 1097 buffer.append("ASN.1 Element"); 1098 buffer.append(EOL); 1099 1100 buffer.append(indentBuf); 1101 buffer.append(" BER Type: "); 1102 buffer.append(byteToHex(type)); 1103 buffer.append(EOL); 1104 1105 buffer.append(indentBuf); 1106 buffer.append(" Value ("); 1107 buffer.append(value.length); 1108 buffer.append(" bytes)"); 1109 buffer.append(EOL); 1110 1111 byteArrayToHexPlusAscii(buffer, value, indent+2); 1112 } 1113 } 1114