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