1 package org.gudy.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      */
DERInputStream( InputStream is)21     public DERInputStream(
22         InputStream is)
23     {
24         super(is);
25     }
26 
readLength()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 stream - negative length found");
66             }
67         }
68 
69         return length;
70     }
71 
readFully( byte[] bytes)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      */
buildObject( int tag, byte[] bytes)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             return new DERBoolean(bytes);
148         case INTEGER:
149             return new DERInteger(bytes);
150         case ENUMERATED:
151             return new DEREnumerated(bytes);
152         case OBJECT_IDENTIFIER:
153             return new DERObjectIdentifier(bytes);
154         case BIT_STRING:
155             int     padBits = bytes[0];
156             byte[]  data = new byte[bytes.length - 1];
157 
158             System.arraycopy(bytes, 1, data, 0, bytes.length - 1);
159 
160             return new DERBitString(data, padBits);
161         case UTF8_STRING:
162             return new DERUTF8String(bytes);
163         case PRINTABLE_STRING:
164             return new DERPrintableString(bytes);
165         case IA5_STRING:
166             return new DERIA5String(bytes);
167         case T61_STRING:
168             return new DERT61String(bytes);
169         case VISIBLE_STRING:
170             return new DERVisibleString(bytes);
171         case UNIVERSAL_STRING:
172             return new DERUniversalString(bytes);
173         case GENERAL_STRING:
174             return new DERGeneralString(bytes);
175         case BMP_STRING:
176             return new DERBMPString(bytes);
177         case OCTET_STRING:
178             return new DEROctetString(bytes);
179         case UTC_TIME:
180             return new DERUTCTime(bytes);
181         case GENERALIZED_TIME:
182             return new DERGeneralizedTime(bytes);
183         default:
184             //
185             // with tagged object tag number is bottom 5 bits
186             //
187             if ((tag & TAGGED) != 0)
188             {
189                 if ((tag & 0x1f) == 0x1f)
190                 {
191                     throw new IOException("unsupported high tag encountered");
192                 }
193 
194                 if (bytes.length == 0)        // empty tag!
195                 {
196                     if ((tag & CONSTRUCTED) == 0)
197                     {
198                         return new DERTaggedObject(false, tag & 0x1f, new DERNull());
199                     }
200                     else
201                     {
202                         return new DERTaggedObject(false, tag & 0x1f, new DERConstructedSequence());
203                     }
204                 }
205 
206                 //
207                 // simple type - implicit... return an octet string
208                 //
209                 if ((tag & CONSTRUCTED) == 0)
210                 {
211                     return new DERTaggedObject(false, tag & 0x1f, new DEROctetString(bytes));
212                 }
213 
214                 bIn = new ByteArrayInputStream(bytes);
215                 dIn = new BERInputStream(bIn);
216 
217                 DEREncodable dObj = dIn.readObject();
218 
219                 //
220                 // explicitly tagged (probably!) - if it isn't we'd have to
221                 // tell from the context
222                 //
223                 if (dIn.available() == 0)
224                 {
225                     return new DERTaggedObject(tag & 0x1f, dObj);
226                 }
227 
228                 //
229                 // another implicit object, we'll create a sequence...
230                 //
231                 seq = new DERConstructedSequence();
232 
233                 seq.addObject(dObj);
234 
235                 try
236                 {
237                     for (;;)
238                     {
239                         dObj = dIn.readObject();
240 
241                         seq.addObject(dObj);
242                     }
243                 }
244                 catch (EOFException ex)
245                 {
246                     // ignore --
247                 }
248 
249                 return new DERTaggedObject(false, tag & 0x1f, seq);
250             }
251 
252             return new DERUnknownTag(tag, bytes);
253         }
254     }
255 
readObject()256     public DERObject readObject()
257         throws IOException
258     {
259         int tag = read();
260         if (tag == -1)
261         {
262             throw new EOFException();
263         }
264 
265         int     length = readLength();
266         byte[]  bytes = new byte[length];
267 
268         readFully(bytes);
269 
270         return buildObject(tag, bytes);
271     }
272 }
273