2003/06/16 08:03:13
[org.ibex.core.git] / src / org / bouncycastle / asn1 / BERInputStream.java
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         int                     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 }