1 package org.bouncycastle.asn1;
2
3 import java.math.BigInteger;
4 import java.io.FilterInputStream;
5
6 import java.io.InputStream;
7 import java.io.ByteArrayInputStream;
8 import java.io.IOException;
9 import java.io.EOFException;
10
11
12 public class DERInputStream
13 extends FilterInputStream implements DERTags
14 {
15 public DERInputStream(
16 InputStream is)
17 {
18 super(is);
19 }
20
21 protected int readLength()
22 throws IOException
23 {
24 int length = read();
25 if (length < 0)
26 {
27 throw new IOException("EOF found when length expected");
28 }
29
30 if (length == 0x80)
31 {
32 return -1;
33 }
34
35 if (length > 127)
36 {
37 int size = length & 0x7f;
38
39 length = 0;
40 for (int i = 0; i < size; i++)
41 {
42 int next = read();
43
44 if (next < 0)
45 {
46 throw new IOException("EOF found reading length");
47 }
48
49 length = (length << 8) + next;
50 }
51 }
52
53 return length;
54 }
55
56 protected void readFully(
57 byte[] bytes)
58 throws IOException
59 {
60 int left = bytes.length;
61
62 if (left == 0)
63 {
64 return;
65 }
66
67 while ((left -= read(bytes, bytes.length - left, left)) != 0)
68 {
69 ;
70 }
71 }
72
73
77 protected DERObject buildObject(
78 int tag,
79 byte[] bytes)
80 throws IOException
81 {
82 switch (tag)
83 {
84 case NULL:
85 return null;
86 case SEQUENCE | CONSTRUCTED:
87 ByteArrayInputStream bIn = new ByteArrayInputStream(bytes);
88 BERInputStream dIn = new BERInputStream(bIn);
89 DERConstructedSequence seq = new DERConstructedSequence();
90
91 try
92 {
93 for (;;)
94 {
95 DERObject obj = dIn.readObject();
96
97 seq.addObject(obj);
98 }
99 }
100 catch (EOFException ex)
101 {
102 return seq;
103 }
104 case SET | CONSTRUCTED:
105 bIn = new ByteArrayInputStream(bytes);
106 dIn = new BERInputStream(bIn);
107
108 DEREncodableVector v = new DEREncodableVector();
109
110 try
111 {
112 for (;;)
113 {
114 DERObject obj = dIn.readObject();
115
116 v.add(obj);
117 }
118 }
119 catch (EOFException ex)
120 {
121 return new DERConstructedSet(v);
122 }
123 case BOOLEAN:
124 return new DERBoolean(bytes);
125 case INTEGER:
126 return new DERInteger(bytes);
127 case ENUMERATED:
128 return new DEREnumerated(bytes);
129 case OBJECT_IDENTIFIER:
130 return new DERObjectIdentifier(bytes);
131 case BIT_STRING:
132 int padBits = bytes[0];
133 byte[] data = new byte[bytes.length - 1];
134
135 System.arraycopy(bytes, 1, data, 0, bytes.length - 1);
136
137 return new DERBitString(data, padBits);
138 case UTF8_STRING:
139 return new DERUTF8String(bytes);
140 case PRINTABLE_STRING:
141 return new DERPrintableString(bytes);
142 case IA5_STRING:
143 return new DERIA5String(bytes);
144 case T61_STRING:
145 return new DERT61String(bytes);
146 case VISIBLE_STRING:
147 return new DERVisibleString(bytes);
148 case UNIVERSAL_STRING:
149 return new DERUniversalString(bytes);
150 case BMP_STRING:
151 return new DERBMPString(bytes);
152 case OCTET_STRING:
153 return new DEROctetString(bytes);
154 case UTC_TIME:
155 return new DERUTCTime(bytes);
156 case GENERALIZED_TIME:
157 return new DERGeneralizedTime(bytes);
158 default:
159
160
161
162 if ((tag & TAGGED) != 0)
163 {
164 if ((tag & 0x1f) == 0x1f)
165 {
166 throw new IOException("unsupported high tag encountered");
167 }
168
169 if (bytes.length == 0)
170 {
171 return new DERTaggedObject(false, tag & 0x1f, new DERConstructedSequence());
172 }
173
174
175
176
177 if ((tag & CONSTRUCTED) == 0)
178 {
179 return new DERTaggedObject(false, tag & 0x1f, new DEROctetString(bytes));
180 }
181
182 bIn = new ByteArrayInputStream(bytes);
183 dIn = new BERInputStream(bIn);
184
185 DEREncodable dObj = dIn.readObject();
186
187
188
189
190
191 if (dIn.available() == 0)
192 {
193 return new DERTaggedObject(tag & 0x1f, dObj);
194 }
195
196
197
198
199 seq = new DERConstructedSequence();
200
201 seq.addObject(dObj);
202
203 try
204 {
205 for (;;)
206 {
207 dObj = dIn.readObject();
208
209 seq.addObject(dObj);
210 }
211 }
212 catch (EOFException ex)
213 {
214
215 }
216
217 return new DERTaggedObject(false, tag & 0x1f, seq);
218 }
219
220 return new DERUnknownTag(tag, bytes);
221 }
222 }
223
224 public DERObject readObject()
225 throws IOException
226 {
227 int tag = read();
228 if (tag == -1)
229 {
230 throw new EOFException();
231 }
232
233 int length = readLength();
234 byte[] bytes = new byte[length];
235
236 readFully(bytes);
237
238 return buildObject(tag, bytes);
239 }
240 }
241