Home | History | Annotate | Download | only in asn1
      1 package org.bouncycastle.asn1;
      2 
      3 import java.io.ByteArrayInputStream;
      4 import java.io.EOFException;
      5 import java.io.FilterInputStream;
      6 import java.io.IOException;
      7 import java.io.InputStream;
      8 
      9 /**
     10  * Don't use this class. It will eventually disappear, use ASN1InputStream.
     11  * <br>
     12  * This class is scheduled for removal.
     13  * @deprecated use ASN1InputStream
     14  */
     15 public class DERInputStream
     16     extends FilterInputStream implements DERTags
     17 {
     18     /**
     19      * @deprecated use ASN1InputStream
     20      */
     21     public DERInputStream(
     22         InputStream is)
     23     {
     24         super(is);
     25     }
     26 
     27     protected int readLength()
     28         throws IOException
     29     {
     30         int length = read();
     31         if (length < 0)
     32         {
     33             throw new IOException("EOF found when length expected");
     34         }
     35 
     36         if (length == 0x80)
     37         {
     38             return -1;      // indefinite-length encoding
     39         }
     40 
     41         if (length > 127)
     42         {
     43             int size = length & 0x7f;
     44 
     45             if (size > 4)
     46             {
     47                 throw new IOException("DER length more than 4 bytes");
     48             }
     49 
     50             length = 0;
     51             for (int i = 0; i < size; i++)
     52             {
     53                 int next = read();
     54 
     55                 if (next < 0)
     56                 {
     57                     throw new IOException("EOF found reading length");
     58                 }
     59 
     60                 length = (length << 8) + next;
     61             }
     62 
     63             if (length < 0)
     64             {
     65                 throw new IOException("corrupted steam - negative length found");
     66             }
     67         }
     68 
     69         return length;
     70     }
     71 
     72     protected void readFully(
     73         byte[]  bytes)
     74         throws IOException
     75     {
     76         int     left = bytes.length;
     77 
     78         if (left == 0)
     79         {
     80             return;
     81         }
     82 
     83         while (left > 0)
     84         {
     85             int    l = read(bytes, bytes.length - left, left);
     86 
     87             if (l < 0)
     88             {
     89                 throw new EOFException("unexpected end of stream");
     90             }
     91 
     92             left -= l;
     93         }
     94     }
     95 
     96     /**
     97      * build an object given its tag and a byte stream to construct it
     98      * from.
     99      */
    100     protected DERObject buildObject(
    101         int       tag,
    102         byte[]    bytes)
    103         throws IOException
    104     {
    105         switch (tag)
    106         {
    107         case NULL:
    108             return null;
    109         case SEQUENCE | CONSTRUCTED:
    110             ByteArrayInputStream    bIn = new ByteArrayInputStream(bytes);
    111             BERInputStream          dIn = new BERInputStream(bIn);
    112             DERConstructedSequence  seq = new DERConstructedSequence();
    113 
    114             try
    115             {
    116                 for (;;)
    117                 {
    118                     DERObject   obj = dIn.readObject();
    119 
    120                     seq.addObject(obj);
    121                 }
    122             }
    123             catch (EOFException ex)
    124             {
    125                 return seq;
    126             }
    127         case SET | CONSTRUCTED:
    128             bIn = new ByteArrayInputStream(bytes);
    129             dIn = new BERInputStream(bIn);
    130 
    131             ASN1EncodableVector    v = new ASN1EncodableVector();
    132 
    133             try
    134             {
    135                 for (;;)
    136                 {
    137                     DERObject   obj = dIn.readObject();
    138 
    139                     v.add(obj);
    140                 }
    141             }
    142             catch (EOFException ex)
    143             {
    144                 return new DERConstructedSet(v);
    145             }
    146         case BOOLEAN:
    147             // BEGIN android-changed
    148             return DERBoolean.getInstance(bytes);
    149             // BEGIN android-changed
    150         case INTEGER:
    151             return new DERInteger(bytes);
    152         case ENUMERATED:
    153             return new DEREnumerated(bytes);
    154         case OBJECT_IDENTIFIER:
    155             return new DERObjectIdentifier(bytes);
    156         case BIT_STRING:
    157             int     padBits = bytes[0];
    158             byte[]  data = new byte[bytes.length - 1];
    159 
    160             System.arraycopy(bytes, 1, data, 0, bytes.length - 1);
    161 
    162             return new DERBitString(data, padBits);
    163         case UTF8_STRING:
    164             return new DERUTF8String(bytes);
    165         case PRINTABLE_STRING:
    166             return new DERPrintableString(bytes);
    167         case IA5_STRING:
    168             return new DERIA5String(bytes);
    169         case T61_STRING:
    170             return new DERT61String(bytes);
    171         case VISIBLE_STRING:
    172             return new DERVisibleString(bytes);
    173         case UNIVERSAL_STRING:
    174             return new DERUniversalString(bytes);
    175         case GENERAL_STRING:
    176             return new DERGeneralString(bytes);
    177         case BMP_STRING:
    178             return new DERBMPString(bytes);
    179         case OCTET_STRING:
    180             return new DEROctetString(bytes);
    181         case UTC_TIME:
    182             return new DERUTCTime(bytes);
    183         case GENERALIZED_TIME:
    184             return new DERGeneralizedTime(bytes);
    185         default:
    186             //
    187             // with tagged object tag number is bottom 5 bits
    188             //
    189             if ((tag & TAGGED) != 0)
    190             {
    191                 if ((tag & 0x1f) == 0x1f)
    192                 {
    193                     throw new IOException("unsupported high tag encountered");
    194                 }
    195 
    196                 if (bytes.length == 0)        // empty tag!
    197                 {
    198                     if ((tag & CONSTRUCTED) == 0)
    199                     {
    200                         // BEGIN android-changed
    201                         return new DERTaggedObject(false, tag & 0x1f, DERNull.THE_ONE);
    202                         // END android-changed
    203                     }
    204                     else
    205                     {
    206                         return new DERTaggedObject(false, tag & 0x1f, new DERConstructedSequence());
    207                     }
    208                 }
    209 
    210                 //
    211                 // simple type - implicit... return an octet string
    212                 //
    213                 if ((tag & CONSTRUCTED) == 0)
    214                 {
    215                     return new DERTaggedObject(false, tag & 0x1f, new DEROctetString(bytes));
    216                 }
    217 
    218                 bIn = new ByteArrayInputStream(bytes);
    219                 dIn = new BERInputStream(bIn);
    220 
    221                 DEREncodable dObj = dIn.readObject();
    222 
    223                 //
    224                 // explicitly tagged (probably!) - if it isn't we'd have to
    225                 // tell from the context
    226                 //
    227                 if (dIn.available() == 0)
    228                 {
    229                     return new DERTaggedObject(tag & 0x1f, dObj);
    230                 }
    231 
    232                 //
    233                 // another implicit object, we'll create a sequence...
    234                 //
    235                 seq = new DERConstructedSequence();
    236 
    237                 seq.addObject(dObj);
    238 
    239                 try
    240                 {
    241                     for (;;)
    242                     {
    243                         dObj = dIn.readObject();
    244 
    245                         seq.addObject(dObj);
    246                     }
    247                 }
    248                 catch (EOFException ex)
    249                 {
    250                     // ignore --
    251                 }
    252 
    253                 return new DERTaggedObject(false, tag & 0x1f, seq);
    254             }
    255 
    256             return new DERUnknownTag(tag, bytes);
    257         }
    258     }
    259 
    260     public DERObject readObject()
    261         throws IOException
    262     {
    263         int tag = read();
    264         if (tag == -1)
    265         {
    266             throw new EOFException();
    267         }
    268 
    269         int     length = readLength();
    270         byte[]  bytes = new byte[length];
    271 
    272         readFully(bytes);
    273 
    274         return buildObject(tag, bytes);
    275     }
    276 }
    277