001/*
002 * Copyright 2007-2020 Ping Identity Corporation
003 * All Rights Reserved.
004 */
005/*
006 * Copyright 2007-2020 Ping Identity Corporation
007 *
008 * Licensed under the Apache License, Version 2.0 (the "License");
009 * you may not use this file except in compliance with the License.
010 * You may obtain a copy of the License at
011 *
012 *    http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing, software
015 * distributed under the License is distributed on an "AS IS" BASIS,
016 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017 * See the License for the specific language governing permissions and
018 * limitations under the License.
019 */
020/*
021 * Copyright (C) 2008-2020 Ping Identity Corporation
022 *
023 * This program is free software; you can redistribute it and/or modify
024 * it under the terms of the GNU General Public License (GPLv2 only)
025 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only)
026 * as published by the Free Software Foundation.
027 *
028 * This program is distributed in the hope that it will be useful,
029 * but WITHOUT ANY WARRANTY; without even the implied warranty of
030 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
031 * GNU General Public License for more details.
032 *
033 * You should have received a copy of the GNU General Public License
034 * along with this program; if not, see <http://www.gnu.org/licenses>.
035 */
036package com.unboundid.asn1;
037
038
039
040import java.io.InputStream;
041import java.io.IOException;
042import java.io.OutputStream;
043import java.io.Serializable;
044import java.util.Arrays;
045
046import com.unboundid.util.ByteStringBuffer;
047import com.unboundid.util.Debug;
048import com.unboundid.util.NotExtensible;
049import com.unboundid.util.NotMutable;
050import com.unboundid.util.StaticUtils;
051import com.unboundid.util.ThreadSafety;
052import com.unboundid.util.ThreadSafetyLevel;
053
054import static com.unboundid.asn1.ASN1Messages.*;
055
056
057
058/**
059 * This class defines a generic ASN.1 BER element, which has a type and value.
060 * It provides a framework for encoding and decoding BER elements, both as
061 * generic elements and more specific subtypes.
062 */
063@NotExtensible()
064@NotMutable()
065@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
066public class ASN1Element
067       implements Serializable
068{
069  /**
070   * The serial version UID for this serializable class.
071   */
072  private static final long serialVersionUID = -1871166128693521335L;
073
074
075
076  // The BER type for this element.
077  private final byte type;
078
079  // The encoded value for this element.
080  private final byte[] value;
081
082  // The cached hashCode for this element.
083  private int hashCode = -1;
084
085  // The number of bytes contained in the value.
086  private final int valueLength;
087
088  // The offset within the value array at which the value begins.
089  private final int valueOffset;
090
091
092
093  /**
094   * Creates a new ASN.1 BER element with the specified type and no value.
095   *
096   * @param  type  The BER type for this element.
097   */
098  public ASN1Element(final byte type)
099  {
100    this.type   = type;
101    value       = ASN1Constants.NO_VALUE;
102    valueOffset = 0;
103    valueLength = 0;
104  }
105
106
107
108  /**
109   * Creates a new ASN1 BER element with the specified type and value.
110   *
111   * @param  type   The BER type for this element.
112   * @param  value  The encoded value for this element.
113   */
114  public ASN1Element(final byte type, final byte[] value)
115  {
116    this.type = type;
117
118    if (value == null)
119    {
120      this.value = ASN1Constants.NO_VALUE;
121    }
122    else
123    {
124      this.value = value;
125    }
126
127    valueOffset = 0;
128    valueLength = this.value.length;
129  }
130
131
132
133  /**
134   * Creates a new ASN1 BER element with the specified type and value.
135   *
136   * @param  type    The BER type for this element.
137   * @param  value   The array containing the encoded value for this element.
138   *                 It must not be {@code null}.
139   * @param  offset  The offset within the array at which the value begins.
140   * @param  length  The number of bytes contained in the value.
141   */
142  public ASN1Element(final byte type, final byte[] value, final int offset,
143                     final int length)
144  {
145    this.type  = type;
146    this.value = value;
147
148    valueOffset = offset;
149    valueLength = length;
150  }
151
152
153
154  /**
155   * Retrieves the BER type for this element.
156   *
157   * @return  The BER type for this element.
158   */
159  public final byte getType()
160  {
161    return type;
162  }
163
164
165
166  /**
167   * Retrieves a value that corresponds to the type class for this element.  The
168   * value returned will be one of
169   * {@link ASN1Constants#TYPE_MASK_UNIVERSAL_CLASS},
170   * {@link ASN1Constants#TYPE_MASK_APPLICATION_CLASS},
171   * {@link ASN1Constants#TYPE_MASK_CONTEXT_SPECIFIC_CLASS}, or
172   * {@link ASN1Constants#TYPE_MASK_PRIVATE_CLASS}.
173   *
174   * @return  A value that corresponds to the type class for this element.
175   */
176  public byte getTypeClass()
177  {
178    return (byte) (type & 0xC0);
179  }
180
181
182
183  /**
184   * Indicates whether the type indicates that this element is constructed.  A
185   * constructed element is one whose value is comprised of the encoded
186   * representation of zero or more ASN.1 elements.  If the type does not
187   * indicate that the element is constructed, then the element is considered
188   * primitive.
189   *
190   * @return  {@code true} if the type indicates that the element is
191   *          constructed, or {@code false} if the type indicates that the
192   *          element is primitive.
193   */
194  public boolean isConstructed()
195  {
196    return ((type & ASN1Constants.TYPE_MASK_PC_CONSTRUCTED) != 0x00);
197  }
198
199
200
201  /**
202   * Retrieves the array containing the value.  The returned array may be
203   * larger than the actual value, so it must be used in conjunction with the
204   * values returned by the {@link #getValueOffset} and {@link #getValueLength}
205   * methods.
206   *
207   * @return  The array containing the value.
208   */
209  byte[] getValueArray()
210  {
211    return value;
212  }
213
214
215
216  /**
217   * Retrieves the position in the value array at which the value actually
218   * begins.
219   *
220   * @return  The position in the value array at which the value actually
221   *          begins.
222   */
223  int getValueOffset()
224  {
225    return valueOffset;
226  }
227
228
229
230  /**
231   * Retrieves the number of bytes contained in the value.
232   *
233   * @return  The number of bytes contained in the value.
234   */
235  public int getValueLength()
236  {
237    return valueLength;
238  }
239
240
241
242  /**
243   * Retrieves the encoded value for this element.
244   *
245   * @return  The encoded value for this element.
246   */
247  public byte[] getValue()
248  {
249    if ((valueOffset == 0) && (valueLength == value.length))
250    {
251      return value;
252    }
253    else
254    {
255      final byte[] returnValue = new byte[valueLength];
256      System.arraycopy(value, valueOffset, returnValue, 0, valueLength);
257      return returnValue;
258    }
259  }
260
261
262
263  /**
264   * Encodes this ASN.1 element to a byte array.
265   *
266   * @return  A byte array containing the encoded representation of this ASN.1
267   *          element.
268   */
269  public final byte[] encode()
270  {
271    final byte[] valueArray = getValueArray();
272    final int    length     = getValueLength();
273    final int    offset     = getValueOffset();
274
275    if (length == 0)
276    {
277      return new byte[] { type, 0x00 };
278    }
279
280    final byte[] lengthBytes  = encodeLength(length);
281    final byte[] elementBytes = new byte[1 + lengthBytes.length + length];
282
283    elementBytes[0] = type;
284    System.arraycopy(lengthBytes, 0, elementBytes, 1, lengthBytes.length);
285    System.arraycopy(valueArray, offset, elementBytes, 1+lengthBytes.length,
286         length);
287
288    return elementBytes;
289  }
290
291
292
293  /**
294   * Encodes the provided length to the given buffer.
295   *
296   * @param  length  The length to be encoded.
297   * @param  buffer  The buffer to which the length should be appended.
298   */
299  static void encodeLengthTo(final int length, final ByteStringBuffer buffer)
300  {
301    if ((length & 0x7F) == length)
302    {
303      buffer.append((byte) length);
304    }
305    else if ((length & 0xFF) == length)
306    {
307      buffer.append((byte) 0x81);
308      buffer.append((byte) (length & 0xFF));
309    }
310    else if ((length & 0xFFFF) == length)
311    {
312      buffer.append((byte) 0x82);
313      buffer.append((byte) ((length >> 8) & 0xFF));
314      buffer.append((byte) (length & 0xFF));
315    }
316    else if ((length & 0x00FF_FFFF) == length)
317    {
318      buffer.append((byte) 0x83);
319      buffer.append((byte) ((length >> 16) & 0xFF));
320      buffer.append((byte) ((length >> 8) & 0xFF));
321      buffer.append((byte) (length & 0xFF));
322    }
323    else
324    {
325      buffer.append((byte) 0x84);
326      buffer.append((byte) ((length >> 24) & 0xFF));
327      buffer.append((byte) ((length >> 16) & 0xFF));
328      buffer.append((byte) ((length >> 8) & 0xFF));
329      buffer.append((byte) (length & 0xFF));
330    }
331  }
332
333
334
335  /**
336   * Appends an encoded representation of this ASN.1 element to the provided
337   * buffer.
338   *
339   * @param  buffer  The buffer to which the encoded representation should be
340   *                 appended.
341   */
342  public void encodeTo(final ByteStringBuffer buffer)
343  {
344    final byte[] valueArray = getValueArray();
345    final int    length     = getValueLength();
346    final int    offset     = getValueOffset();
347
348    buffer.append(type);
349    if (length == 0)
350    {
351      buffer.append((byte) 0x00);
352    }
353    else
354    {
355      encodeLengthTo(length, buffer);
356      buffer.append(valueArray, offset, length);
357    }
358  }
359
360
361
362  /**
363   * Encodes the provided length to a byte array.
364   *
365   * @param  length  The length to be encoded.
366   *
367   * @return  A byte array containing the encoded length.
368   */
369  public static byte[] encodeLength(final int length)
370  {
371    switch (length)
372    {
373      case 0:  return ASN1Constants.LENGTH_0;
374      case 1:  return ASN1Constants.LENGTH_1;
375      case 2:  return ASN1Constants.LENGTH_2;
376      case 3:  return ASN1Constants.LENGTH_3;
377      case 4:  return ASN1Constants.LENGTH_4;
378      case 5:  return ASN1Constants.LENGTH_5;
379      case 6:  return ASN1Constants.LENGTH_6;
380      case 7:  return ASN1Constants.LENGTH_7;
381      case 8:  return ASN1Constants.LENGTH_8;
382      case 9:  return ASN1Constants.LENGTH_9;
383      case 10:  return ASN1Constants.LENGTH_10;
384      case 11:  return ASN1Constants.LENGTH_11;
385      case 12:  return ASN1Constants.LENGTH_12;
386      case 13:  return ASN1Constants.LENGTH_13;
387      case 14:  return ASN1Constants.LENGTH_14;
388      case 15:  return ASN1Constants.LENGTH_15;
389      case 16:  return ASN1Constants.LENGTH_16;
390      case 17:  return ASN1Constants.LENGTH_17;
391      case 18:  return ASN1Constants.LENGTH_18;
392      case 19:  return ASN1Constants.LENGTH_19;
393      case 20:  return ASN1Constants.LENGTH_20;
394      case 21:  return ASN1Constants.LENGTH_21;
395      case 22:  return ASN1Constants.LENGTH_22;
396      case 23:  return ASN1Constants.LENGTH_23;
397      case 24:  return ASN1Constants.LENGTH_24;
398      case 25:  return ASN1Constants.LENGTH_25;
399      case 26:  return ASN1Constants.LENGTH_26;
400      case 27:  return ASN1Constants.LENGTH_27;
401      case 28:  return ASN1Constants.LENGTH_28;
402      case 29:  return ASN1Constants.LENGTH_29;
403      case 30:  return ASN1Constants.LENGTH_30;
404      case 31:  return ASN1Constants.LENGTH_31;
405      case 32:  return ASN1Constants.LENGTH_32;
406      case 33:  return ASN1Constants.LENGTH_33;
407      case 34:  return ASN1Constants.LENGTH_34;
408      case 35:  return ASN1Constants.LENGTH_35;
409      case 36:  return ASN1Constants.LENGTH_36;
410      case 37:  return ASN1Constants.LENGTH_37;
411      case 38:  return ASN1Constants.LENGTH_38;
412      case 39:  return ASN1Constants.LENGTH_39;
413      case 40:  return ASN1Constants.LENGTH_40;
414      case 41:  return ASN1Constants.LENGTH_41;
415      case 42:  return ASN1Constants.LENGTH_42;
416      case 43:  return ASN1Constants.LENGTH_43;
417      case 44:  return ASN1Constants.LENGTH_44;
418      case 45:  return ASN1Constants.LENGTH_45;
419      case 46:  return ASN1Constants.LENGTH_46;
420      case 47:  return ASN1Constants.LENGTH_47;
421      case 48:  return ASN1Constants.LENGTH_48;
422      case 49:  return ASN1Constants.LENGTH_49;
423      case 50:  return ASN1Constants.LENGTH_50;
424      case 51:  return ASN1Constants.LENGTH_51;
425      case 52:  return ASN1Constants.LENGTH_52;
426      case 53:  return ASN1Constants.LENGTH_53;
427      case 54:  return ASN1Constants.LENGTH_54;
428      case 55:  return ASN1Constants.LENGTH_55;
429      case 56:  return ASN1Constants.LENGTH_56;
430      case 57:  return ASN1Constants.LENGTH_57;
431      case 58:  return ASN1Constants.LENGTH_58;
432      case 59:  return ASN1Constants.LENGTH_59;
433      case 60:  return ASN1Constants.LENGTH_60;
434      case 61:  return ASN1Constants.LENGTH_61;
435      case 62:  return ASN1Constants.LENGTH_62;
436      case 63:  return ASN1Constants.LENGTH_63;
437      case 64:  return ASN1Constants.LENGTH_64;
438      case 65:  return ASN1Constants.LENGTH_65;
439      case 66:  return ASN1Constants.LENGTH_66;
440      case 67:  return ASN1Constants.LENGTH_67;
441      case 68:  return ASN1Constants.LENGTH_68;
442      case 69:  return ASN1Constants.LENGTH_69;
443      case 70:  return ASN1Constants.LENGTH_70;
444      case 71:  return ASN1Constants.LENGTH_71;
445      case 72:  return ASN1Constants.LENGTH_72;
446      case 73:  return ASN1Constants.LENGTH_73;
447      case 74:  return ASN1Constants.LENGTH_74;
448      case 75:  return ASN1Constants.LENGTH_75;
449      case 76:  return ASN1Constants.LENGTH_76;
450      case 77:  return ASN1Constants.LENGTH_77;
451      case 78:  return ASN1Constants.LENGTH_78;
452      case 79:  return ASN1Constants.LENGTH_79;
453      case 80:  return ASN1Constants.LENGTH_80;
454      case 81:  return ASN1Constants.LENGTH_81;
455      case 82:  return ASN1Constants.LENGTH_82;
456      case 83:  return ASN1Constants.LENGTH_83;
457      case 84:  return ASN1Constants.LENGTH_84;
458      case 85:  return ASN1Constants.LENGTH_85;
459      case 86:  return ASN1Constants.LENGTH_86;
460      case 87:  return ASN1Constants.LENGTH_87;
461      case 88:  return ASN1Constants.LENGTH_88;
462      case 89:  return ASN1Constants.LENGTH_89;
463      case 90:  return ASN1Constants.LENGTH_90;
464      case 91:  return ASN1Constants.LENGTH_91;
465      case 92:  return ASN1Constants.LENGTH_92;
466      case 93:  return ASN1Constants.LENGTH_93;
467      case 94:  return ASN1Constants.LENGTH_94;
468      case 95:  return ASN1Constants.LENGTH_95;
469      case 96:  return ASN1Constants.LENGTH_96;
470      case 97:  return ASN1Constants.LENGTH_97;
471      case 98:  return ASN1Constants.LENGTH_98;
472      case 99:  return ASN1Constants.LENGTH_99;
473      case 100:  return ASN1Constants.LENGTH_100;
474      case 101:  return ASN1Constants.LENGTH_101;
475      case 102:  return ASN1Constants.LENGTH_102;
476      case 103:  return ASN1Constants.LENGTH_103;
477      case 104:  return ASN1Constants.LENGTH_104;
478      case 105:  return ASN1Constants.LENGTH_105;
479      case 106:  return ASN1Constants.LENGTH_106;
480      case 107:  return ASN1Constants.LENGTH_107;
481      case 108:  return ASN1Constants.LENGTH_108;
482      case 109:  return ASN1Constants.LENGTH_109;
483      case 110:  return ASN1Constants.LENGTH_110;
484      case 111:  return ASN1Constants.LENGTH_111;
485      case 112:  return ASN1Constants.LENGTH_112;
486      case 113:  return ASN1Constants.LENGTH_113;
487      case 114:  return ASN1Constants.LENGTH_114;
488      case 115:  return ASN1Constants.LENGTH_115;
489      case 116:  return ASN1Constants.LENGTH_116;
490      case 117:  return ASN1Constants.LENGTH_117;
491      case 118:  return ASN1Constants.LENGTH_118;
492      case 119:  return ASN1Constants.LENGTH_119;
493      case 120:  return ASN1Constants.LENGTH_120;
494      case 121:  return ASN1Constants.LENGTH_121;
495      case 122:  return ASN1Constants.LENGTH_122;
496      case 123:  return ASN1Constants.LENGTH_123;
497      case 124:  return ASN1Constants.LENGTH_124;
498      case 125:  return ASN1Constants.LENGTH_125;
499      case 126:  return ASN1Constants.LENGTH_126;
500      case 127:  return ASN1Constants.LENGTH_127;
501    }
502
503    if ((length & 0x0000_00FF) == length)
504    {
505      return new byte[]
506      {
507        (byte) 0x81,
508        (byte) (length & 0xFF)
509      };
510    }
511    else if ((length & 0x0000_FFFF) == length)
512    {
513      return new byte[]
514      {
515        (byte) 0x82,
516        (byte) ((length >> 8) & 0xFF),
517        (byte) (length & 0xFF)
518      };
519    }
520    else if ((length & 0x00FF_FFFF) == length)
521    {
522      return new byte[]
523      {
524        (byte) 0x83,
525        (byte) ((length >> 16) & 0xFF),
526        (byte) ((length >> 8) & 0xFF),
527        (byte) (length & 0xFF)
528      };
529    }
530    else
531    {
532      return new byte[]
533      {
534        (byte) 0x84,
535        (byte) ((length >> 24) & 0xFF),
536        (byte) ((length >> 16) & 0xFF),
537        (byte) ((length >> 8) & 0xFF),
538        (byte) (length & 0xFF)
539      };
540    }
541  }
542
543
544
545  /**
546   * Decodes the content in the provided byte array as an ASN.1 element.
547   *
548   * @param  elementBytes  The byte array containing the data to decode.
549   *
550   * @return  The decoded ASN.1 BER element.
551   *
552   * @throws  ASN1Exception  If the provided byte array does not represent a
553   *                         valid ASN.1 element.
554   */
555  public static ASN1Element decode(final byte[] elementBytes)
556         throws ASN1Exception
557  {
558    try
559    {
560      int valueStartPos = 2;
561      int length = (elementBytes[1] & 0x7F);
562      if (length != elementBytes[1])
563      {
564        final int numLengthBytes = length;
565
566        length = 0;
567        for (int i=0; i < numLengthBytes; i++)
568        {
569          length <<= 8;
570          length |= (elementBytes[valueStartPos++] & 0xFF);
571        }
572      }
573
574      if ((elementBytes.length - valueStartPos) != length)
575      {
576        throw new ASN1Exception(ERR_ELEMENT_LENGTH_MISMATCH.get(length,
577                                     (elementBytes.length - valueStartPos)));
578      }
579
580      final byte[] value = new byte[length];
581      System.arraycopy(elementBytes, valueStartPos, value, 0, length);
582      return new ASN1Element(elementBytes[0], value);
583    }
584    catch (final ASN1Exception ae)
585    {
586      Debug.debugException(ae);
587      throw ae;
588    }
589    catch (final Exception e)
590    {
591      Debug.debugException(e);
592      throw new ASN1Exception(ERR_ELEMENT_DECODE_EXCEPTION.get(e), e);
593    }
594  }
595
596
597
598  /**
599   * Decodes this ASN.1 element as a bit string element.
600   *
601   * @return  The decoded bit string element.
602   *
603   * @throws  ASN1Exception  If this element cannot be decoded as a bit string
604   *                         element.
605   */
606  public final ASN1BitString decodeAsBitString()
607         throws ASN1Exception
608  {
609    return ASN1BitString.decodeAsBitString(this);
610  }
611
612
613
614  /**
615   * Decodes this ASN.1 element as a Boolean element.
616   *
617   * @return  The decoded Boolean element.
618   *
619   * @throws  ASN1Exception  If this element cannot be decoded as a Boolean
620   *                         element.
621   */
622  public final ASN1Boolean decodeAsBoolean()
623         throws ASN1Exception
624  {
625    return ASN1Boolean.decodeAsBoolean(this);
626  }
627
628
629
630  /**
631   * Decodes this ASN.1 element as an enumerated element.
632   *
633   * @return  The decoded enumerated element.
634   *
635   * @throws  ASN1Exception  If this element cannot be decoded as an enumerated
636   *                         element.
637   */
638  public final ASN1Enumerated decodeAsEnumerated()
639         throws ASN1Exception
640  {
641    return ASN1Enumerated.decodeAsEnumerated(this);
642  }
643
644
645
646  /**
647   * Decodes this ASN.1 element as a generalized time element.
648   *
649   * @return  The decoded generalized time element.
650   *
651   * @throws  ASN1Exception  If this element cannot be decoded as a generalized
652   *                         time element.
653   */
654  public final ASN1GeneralizedTime decodeAsGeneralizedTime()
655         throws ASN1Exception
656  {
657    return ASN1GeneralizedTime.decodeAsGeneralizedTime(this);
658  }
659
660
661
662  /**
663   * Decodes this ASN.1 element as an IA5 string element.
664   *
665   * @return  The decoded IA5 string element.
666   *
667   * @throws  ASN1Exception  If this element cannot be decoded as a IA5 string
668   *                         element.
669   */
670  public final ASN1IA5String decodeAsIA5String()
671         throws ASN1Exception
672  {
673    return ASN1IA5String.decodeAsIA5String(this);
674  }
675
676
677
678  /**
679   * Decodes this ASN.1 element as an integer element.
680   *
681   * @return  The decoded integer element.
682   *
683   * @throws  ASN1Exception  If this element cannot be decoded as an integer
684   *                         element.
685   */
686  public final ASN1Integer decodeAsInteger()
687         throws ASN1Exception
688  {
689    return ASN1Integer.decodeAsInteger(this);
690  }
691
692
693
694  /**
695   * Decodes this ASN.1 element as a long element.
696   *
697   * @return  The decoded long element.
698   *
699   * @throws  ASN1Exception  If this element cannot be decoded as a long
700   *                         element.
701   */
702  public final ASN1Long decodeAsLong()
703         throws ASN1Exception
704  {
705    return ASN1Long.decodeAsLong(this);
706  }
707
708
709
710  /**
711   * Decodes this ASN.1 element as a big integer element.
712   *
713   * @return  The decoded big integer element.
714   *
715   * @throws  ASN1Exception  If this element cannot be decoded as a big integer
716   *                         element.
717   */
718  public final ASN1BigInteger decodeAsBigInteger()
719         throws ASN1Exception
720  {
721    return ASN1BigInteger.decodeAsBigInteger(this);
722  }
723
724
725
726  /**
727   * Decodes this ASN.1 element as a null element.
728   *
729   * @return  The decoded null element.
730   *
731   * @throws  ASN1Exception  If this element cannot be decoded as a null
732   *                         element.
733   */
734  public final ASN1Null decodeAsNull()
735         throws ASN1Exception
736  {
737    return ASN1Null.decodeAsNull(this);
738  }
739
740
741
742  /**
743   * Decodes this ASN.1 element as a numeric string element.
744   *
745   * @return  The decoded numeric string element.
746   *
747   * @throws  ASN1Exception  If this element cannot be decoded as a numeric
748   *                         string element.
749   */
750  public final ASN1NumericString decodeAsNumericString()
751         throws ASN1Exception
752  {
753    return ASN1NumericString.decodeAsNumericString(this);
754  }
755
756
757
758  /**
759   * Decodes this ASN.1 element as an object identifier element.
760   *
761   * @return  The decoded object identifier element.
762   *
763   * @throws  ASN1Exception  If this element cannot be decoded as an object
764   *                         identifier element.
765   */
766  public final ASN1ObjectIdentifier decodeAsObjectIdentifier()
767         throws ASN1Exception
768  {
769    return ASN1ObjectIdentifier.decodeAsObjectIdentifier(this);
770  }
771
772
773
774  /**
775   * Decodes this ASN.1 element as an octet string element.
776   *
777   * @return  The decoded octet string element.
778   */
779  public final ASN1OctetString decodeAsOctetString()
780  {
781    return ASN1OctetString.decodeAsOctetString(this);
782  }
783
784
785
786  /**
787   * Decodes this ASN.1 element as a printable string element.
788   *
789   * @return  The decoded printable string element.
790   *
791   * @throws  ASN1Exception  If this element cannot be decoded as a printable
792   *                         string element.
793   */
794  public final ASN1PrintableString decodeAsPrintableString()
795         throws ASN1Exception
796  {
797    return ASN1PrintableString.decodeAsPrintableString(this);
798  }
799
800
801
802  /**
803   * Decodes this ASN.1 element as a sequence element.
804   *
805   * @return  The decoded sequence element.
806   *
807   * @throws  ASN1Exception  If this element cannot be decoded as a sequence
808   *                         element.
809   */
810  public final ASN1Sequence decodeAsSequence()
811         throws ASN1Exception
812  {
813    return ASN1Sequence.decodeAsSequence(this);
814  }
815
816
817
818  /**
819   * Decodes this ASN.1 element as a set element.
820   *
821   * @return  The decoded set element.
822   *
823   * @throws  ASN1Exception  If this element cannot be decoded as a set
824   *                         element.
825   */
826  public final ASN1Set decodeAsSet()
827         throws ASN1Exception
828  {
829    return ASN1Set.decodeAsSet(this);
830  }
831
832
833
834  /**
835   * Decodes this ASN.1 element as a UTC time element.
836   *
837   * @return  The decoded UTC time element.
838   *
839   * @throws  ASN1Exception  If this element cannot be decoded as a UTC time
840   *                         element.
841   */
842  public final ASN1UTCTime decodeAsUTCTime()
843         throws ASN1Exception
844  {
845    return ASN1UTCTime.decodeAsUTCTime(this);
846  }
847
848
849
850  /**
851   * Decodes this ASN.1 element as a UTF-8 string element.
852   *
853   * @return  The decoded UTF_8 string element.
854   *
855   * @throws  ASN1Exception  If this element cannot be decoded as a UTF-8
856   *                         string element.
857   */
858  public final ASN1UTF8String decodeAsUTF8String()
859         throws ASN1Exception
860  {
861    return ASN1UTF8String.decodeAsUTF8String(this);
862  }
863
864
865
866  /**
867   * Reads an ASN.1 element from the provided input stream.
868   *
869   * @param  inputStream  The input stream from which to read the element.
870   *
871   * @return  The element read from the input stream, or {@code null} if the end
872   *          of the input stream is reached without reading any data.
873   *
874   * @throws  IOException  If a problem occurs while attempting to read from the
875   *                       input stream.
876   *
877   * @throws  ASN1Exception  If a problem occurs while attempting to decode the
878   *                         element.
879   */
880  public static ASN1Element readFrom(final InputStream inputStream)
881         throws IOException, ASN1Exception
882  {
883    return readFrom(inputStream, -1);
884  }
885
886
887
888  /**
889   * Reads an ASN.1 element from the provided input stream.
890   *
891   * @param  inputStream  The input stream from which to read the element.
892   * @param  maxSize      The maximum value size in bytes that will be allowed.
893   *                      A value less than or equal to zero indicates that no
894   *                      maximum size should be enforced.  An attempt to read
895   *                      an element with a value larger than this will cause an
896   *                      {@code ASN1Exception} to be thrown.
897   *
898   * @return  The element read from the input stream, or {@code null} if the end
899   *          of the input stream is reached without reading any data.
900   *
901   * @throws  IOException  If a problem occurs while attempting to read from the
902   *                       input stream.
903   *
904   * @throws  ASN1Exception  If a problem occurs while attempting to decode the
905   *                         element.
906   */
907  public static ASN1Element readFrom(final InputStream inputStream,
908                                     final int maxSize)
909         throws IOException, ASN1Exception
910  {
911    final int typeInt = inputStream.read();
912    if (typeInt < 0)
913    {
914      return null;
915    }
916
917    final byte type = (byte) typeInt;
918
919    int length = inputStream.read();
920    if (length < 0)
921    {
922      throw new ASN1Exception(ERR_READ_END_BEFORE_FIRST_LENGTH.get());
923    }
924    else if (length > 127)
925    {
926      final int numLengthBytes = length & 0x7F;
927      length = 0;
928      if ((numLengthBytes < 1) || (numLengthBytes > 4))
929      {
930        throw new ASN1Exception(ERR_READ_LENGTH_TOO_LONG.get(numLengthBytes));
931      }
932
933      for (int i=0; i < numLengthBytes; i++)
934      {
935        final int lengthInt = inputStream.read();
936        if (lengthInt < 0)
937        {
938          throw new ASN1Exception(ERR_READ_END_BEFORE_LENGTH_END.get());
939        }
940
941        length <<= 8;
942        length |= (lengthInt & 0xFF);
943      }
944    }
945
946    if ((length < 0) || ((maxSize > 0) && (length > maxSize)))
947    {
948      throw new ASN1Exception(ERR_READ_LENGTH_EXCEEDS_MAX.get(length, maxSize));
949    }
950
951    int totalBytesRead = 0;
952    int bytesRemaining = length;
953    final byte[] value = new byte[length];
954    while (totalBytesRead < length)
955    {
956      final int bytesRead =
957           inputStream.read(value, totalBytesRead, bytesRemaining);
958      if (bytesRead < 0)
959      {
960        throw new ASN1Exception(ERR_READ_END_BEFORE_VALUE_END.get());
961      }
962
963      totalBytesRead += bytesRead;
964      bytesRemaining -= bytesRead;
965    }
966
967    final ASN1Element e = new ASN1Element(type, value);
968    Debug.debugASN1Read(e);
969    return e;
970  }
971
972
973
974  /**
975   * Writes an encoded representation of this ASN.1 element to the provided
976   * output stream.
977   *
978   * @param  outputStream  The output stream to which the element should be
979   *                       written.
980   *
981   * @return  The total number of bytes written to the output stream.
982   *
983   * @throws  IOException  If a problem occurs while attempting to write to the
984   *                       provided output stream.
985   *
986   * @see  ASN1Writer#writeElement(ASN1Element,OutputStream)
987   */
988  public final int writeTo(final OutputStream outputStream)
989         throws IOException
990  {
991    Debug.debugASN1Write(this);
992
993    final ByteStringBuffer buffer = new ByteStringBuffer();
994    encodeTo(buffer);
995    buffer.write(outputStream);
996    return buffer.length();
997  }
998
999
1000
1001  /**
1002   * Retrieves a hash code for this ASN.1 BER element.
1003   *
1004   * @return  A hash code for this ASN.1 BER element.
1005   */
1006  @Override()
1007  public final int hashCode()
1008  {
1009    if (hashCode == -1)
1010    {
1011      int hash = 0;
1012      for (final byte b : getValue())
1013      {
1014        hash = hash * 31 + b;
1015      }
1016      hashCode = hash;
1017    }
1018
1019    return hashCode;
1020  }
1021
1022
1023
1024  /**
1025   * Indicates whether the provided object is equal to this ASN.1 BER element.
1026   * The object will only be considered equal to this ASN.1 element if it is a
1027   * non-null ASN.1 element with the same type and value as this element.
1028   *
1029   * @param  o  The object for which to make the determination.
1030   *
1031   * @return  {@code true} if the provided object is considered equal to this
1032   *          ASN.1 element, or {@code false} if not.
1033   */
1034  @Override()
1035  public final boolean equals(final Object o)
1036  {
1037    if (o == null)
1038    {
1039      return false;
1040    }
1041
1042    if (o == this)
1043    {
1044      return true;
1045    }
1046
1047    try
1048    {
1049      final ASN1Element e = (ASN1Element) o;
1050      return ((type == e.getType()) && Arrays.equals(getValue(), e.getValue()));
1051    }
1052    catch (final Exception e)
1053    {
1054      Debug.debugException(e);
1055      return false;
1056    }
1057  }
1058
1059
1060
1061  /**
1062   * Indicates whether the provided ASN.1 element is equal to this element,
1063   * ignoring any potential difference in the BER type.
1064   *
1065   * @param  element  The ASN.1 BER element for which to make the determination.
1066   *
1067   * @return  {@code true} if the provided ASN.1 element is considered equal to
1068   *          this element (ignoring type differences), or {@code false} if not.
1069   */
1070  public final boolean equalsIgnoreType(final ASN1Element element)
1071  {
1072    if (element == null)
1073    {
1074      return false;
1075    }
1076
1077    if (element == this)
1078    {
1079      return true;
1080    }
1081
1082    return Arrays.equals(getValue(), element.getValue());
1083  }
1084
1085
1086
1087  /**
1088   * Retrieves a string representation of the value for ASN.1 element.
1089   *
1090   * @return  A string representation of the value for this ASN.1 element.
1091   */
1092  @Override()
1093  public final String toString()
1094  {
1095    final StringBuilder buffer = new StringBuilder();
1096    toString(buffer);
1097    return buffer.toString();
1098  }
1099
1100
1101
1102  /**
1103   * Appends a string representation of the value for this ASN.1 element to the
1104   * provided buffer.
1105   *
1106   * @param  buffer  The buffer to which to append the information.
1107   */
1108  public void toString(final StringBuilder buffer)
1109  {
1110    final byte[] v = getValue();
1111    buffer.append("ASN1Element(type=");
1112    StaticUtils.toHex(type, buffer);
1113    buffer.append(", valueLength=");
1114    buffer.append(v.length);
1115    buffer.append(", valueBytes='");
1116    StaticUtils.toHex(v, buffer);
1117    buffer.append("')");
1118  }
1119}