1    package org.bouncycastle.asn1;
2    
3    import java.math.BigInteger;
4    import java.io.*;
5    import java.util.*;
6    
7    public class BERInputStream
8        extends DERInputStream
9    {
10           private DERObject END_OF_STREAM = new DERObject() {
11                                                                                   void encode(
12                                                                                           DEROutputStream out)
13                                                                                   throws IOException
14                                                                                   {
15                                                                                           throw new IOException("Eeek!");
16                                                                                   }
17   
18                                                                           };
19       public BERInputStream(
20           InputStream is)
21       {
22           super(is);
23       }
24   
25       /**
26        * read a string of bytes representing an indefinite length object.
27        */
28       private byte[] readIndefiniteLengthFully()
29           throws IOException
30       {
31           ByteArrayOutputStream   bOut = new ByteArrayOutputStream();
32           intint                  b, b1;
33   
34           b1 = read();
35   
36           while ((b = read()) >= 0)
37           {
38                           if (b1 == 0 && b == 0)
39                           {
40                                   break;
41                           }
42   
43               bOut.write(b1);
44               b1 = b;
45           }
46   
47           return bOut.toByteArray();
48       }
49   
50           private BERConstructedOctetString buildConstructedOctetString()
51                   throws IOException
52           {
53           Vector                  octs = new Vector();
54   
55                   for (;;)
56                   {
57                           DERObject               o = readObject();
58   
59                           if (o == END_OF_STREAM)
60                           {
61                                   break;
62                           }
63   
64               octs.addElement(o);
65                   }
66   
67                   return new BERConstructedOctetString(octs);
68           }
69   
70       public DERObject readObject()
71           throws IOException
72       {
73           int tag = read();
74           if (tag == -1)
75           {
76               throw new EOFException();
77           }
78       
79           int     length = readLength();
80   
81           if (length < 0)    // indefinite length method
82           {
83               switch (tag)
84               {
85               case NULL:
86                   return null;
87               case SEQUENCE | CONSTRUCTED:
88                   BERConstructedSequence  seq = new BERConstructedSequence();
89       
90                                   for (;;)
91                                   {
92                                           DERObject   obj = readObject();
93   
94                                           if (obj == END_OF_STREAM)
95                                           {
96                                                   break;
97                                           }
98   
99                                           seq.addObject(obj);
100                                  }
101                                  return seq;
102              case OCTET_STRING | CONSTRUCTED:
103                                  return buildConstructedOctetString();
104              case SET | CONSTRUCTED:
105                  DEREncodableVector  v = new DEREncodableVector();
106      
107                                  for (;;)
108                                  {
109                                          DERObject   obj = readObject();
110  
111                                          if (obj == END_OF_STREAM)
112                                          {
113                                                  break;
114                                          }
115  
116                                          v.add(obj);
117                                  }
118                                  return new BERSet(v);
119              default:
120                  //
121                  // with tagged object tag number is bottom 5 bits
122                  //
123                  if ((tag & TAGGED) != 0)  
124                  {
125                      if ((tag & 0x1f) == 0x1f)
126                      {
127                          throw new IOException("unsupported high tag encountered");
128                      }
129  
130                      //
131                      // simple type - implicit... return an octet string
132                      //
133                      if ((tag & CONSTRUCTED) == 0)
134                      {
135                          byte[]  bytes = readIndefiniteLengthFully();
136  
137                          return new BERTaggedObject(false, tag & 0x1f, new DEROctetString(bytes));
138                      }
139  
140                      //
141                      // either constructed or explicitly tagged
142                      //
143                                          DERObject               dObj = readObject();
144  
145                                          if (dObj == END_OF_STREAM)     // empty tag!
146                      {
147                          return new DERTaggedObject(tag & 0x1f);
148                      }
149  
150                      DERObject       next = readObject();
151  
152                      //
153                      // explicitly tagged (probably!) - if it isn't we'd have to
154                      // tell from the context
155                      //
156                      if (next == END_OF_STREAM)
157                      {
158                          return new BERTaggedObject(tag & 0x1f, dObj);
159                      }
160  
161                      //
162                      // another implicit object, we'll create a sequence...
163                      //
164                      seq = new BERConstructedSequence();
165  
166                      seq.addObject(dObj);
167  
168                      do
169                      {
170                          seq.addObject(next);
171                          next = readObject();
172                      }
173                      while (next != END_OF_STREAM);
174  
175                      return new BERTaggedObject(false, tag & 0x1f, seq);
176                  }
177  
178                  throw new IOException("unknown BER object encountered");
179              }
180          }
181          else
182          {
183              if (tag == 0 && length == 0)    // end of contents marker.
184              {
185                  return END_OF_STREAM;
186              }
187  
188              byte[]  bytes = new byte[length];
189      
190              readFully(bytes);
191      
192                          return buildObject(tag, bytes);
193          }
194      }
195  }
196