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