1 /**
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one or more
4 * contributor license agreements. See the NOTICE file distributed with
5 * this work for additional information regarding copyright ownership.
6 * The ASF licenses this file to You under the Apache License, Version 2.0
7 * (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19 package org.apache.geronimo.util.asn1;
20
21 import java.io.ByteArrayInputStream;
22 import java.io.EOFException;
23 import java.io.FilterInputStream;
24 import java.io.IOException;
25 import java.io.InputStream;
26
27 /**
28 * Don't use this class. It will eventually disappear, use ASN1InputStream.
29 * <br>
30 * This class is scheduled for removal.
31 * @deprecated use ASN1InputStream
32 */
33 public class DERInputStream
34 extends FilterInputStream implements DERTags
35 {
36 /**
37 * @deprecated use ASN1InputStream
38 */
39 public DERInputStream(
40 InputStream is)
41 {
42 super(is);
43 }
44
45 protected int readLength()
46 throws IOException
47 {
48 int length = read();
49 if (length < 0)
50 {
51 throw new IOException("EOF found when length expected");
52 }
53
54 if (length == 0x80)
55 {
56 return -1;
57 }
58
59 if (length > 127)
60 {
61 int size = length & 0x7f;
62
63 if (size > 4)
64 {
65 throw new IOException("DER length more than 4 bytes");
66 }
67
68 length = 0;
69 for (int i = 0; i < size; i++)
70 {
71 int next = read();
72
73 if (next < 0)
74 {
75 throw new IOException("EOF found reading length");
76 }
77
78 length = (length << 8) + next;
79 }
80
81 if (length < 0)
82 {
83 throw new IOException("corrupted steam - negative length found");
84 }
85 }
86
87 return length;
88 }
89
90 protected void readFully(
91 byte[] bytes)
92 throws IOException
93 {
94 int left = bytes.length;
95
96 if (left == 0)
97 {
98 return;
99 }
100
101 while (left > 0)
102 {
103 int l = read(bytes, bytes.length - left, left);
104
105 if (l < 0)
106 {
107 throw new EOFException("unexpected end of stream");
108 }
109
110 left -= l;
111 }
112 }
113
114 /**
115 * build an object given its tag and a byte stream to construct it
116 * from.
117 */
118 protected DERObject buildObject(
119 int tag,
120 byte[] bytes)
121 throws IOException
122 {
123 switch (tag)
124 {
125 case NULL:
126 return null;
127 case SEQUENCE | CONSTRUCTED:
128 ByteArrayInputStream bIn = new ByteArrayInputStream(bytes);
129 BERInputStream dIn = new BERInputStream(bIn);
130 DERConstructedSequence seq = new DERConstructedSequence();
131
132 try
133 {
134 for (;;)
135 {
136 DERObject obj = dIn.readObject();
137
138 seq.addObject(obj);
139 }
140 }
141 catch (EOFException ex)
142 {
143 return seq;
144 }
145 case SET | CONSTRUCTED:
146 bIn = new ByteArrayInputStream(bytes);
147 dIn = new BERInputStream(bIn);
148
149 ASN1EncodableVector v = new ASN1EncodableVector();
150
151 try
152 {
153 for (;;)
154 {
155 DERObject obj = dIn.readObject();
156
157 v.add(obj);
158 }
159 }
160 catch (EOFException ex)
161 {
162 return new DERConstructedSet(v);
163 }
164 case BOOLEAN:
165 return new DERBoolean(bytes);
166 case INTEGER:
167 return new DERInteger(bytes);
168 case ENUMERATED:
169 return new DEREnumerated(bytes);
170 case OBJECT_IDENTIFIER:
171 return new DERObjectIdentifier(bytes);
172 case BIT_STRING:
173 int padBits = bytes[0];
174 byte[] data = new byte[bytes.length - 1];
175
176 System.arraycopy(bytes, 1, data, 0, bytes.length - 1);
177
178 return new DERBitString(data, padBits);
179 case UTF8_STRING:
180 return new DERUTF8String(bytes);
181 case PRINTABLE_STRING:
182 return new DERPrintableString(bytes);
183 case IA5_STRING:
184 return new DERIA5String(bytes);
185 case T61_STRING:
186 return new DERT61String(bytes);
187 case VISIBLE_STRING:
188 return new DERVisibleString(bytes);
189 case UNIVERSAL_STRING:
190 return new DERUniversalString(bytes);
191 case GENERAL_STRING:
192 return new DERGeneralString(bytes);
193 case BMP_STRING:
194 return new DERBMPString(bytes);
195 case OCTET_STRING:
196 return new DEROctetString(bytes);
197 case UTC_TIME:
198 return new DERUTCTime(bytes);
199 case GENERALIZED_TIME:
200 return new DERGeneralizedTime(bytes);
201 default:
202
203
204
205 if ((tag & TAGGED) != 0)
206 {
207 if ((tag & 0x1f) == 0x1f)
208 {
209 throw new IOException("unsupported high tag encountered");
210 }
211
212 if (bytes.length == 0)
213 {
214 if ((tag & CONSTRUCTED) == 0)
215 {
216 return new DERTaggedObject(false, tag & 0x1f, new DERNull());
217 }
218 else
219 {
220 return new DERTaggedObject(false, tag & 0x1f, new DERConstructedSequence());
221 }
222 }
223
224
225
226
227 if ((tag & CONSTRUCTED) == 0)
228 {
229 return new DERTaggedObject(false, tag & 0x1f, new DEROctetString(bytes));
230 }
231
232 bIn = new ByteArrayInputStream(bytes);
233 dIn = new BERInputStream(bIn);
234
235 DEREncodable dObj = dIn.readObject();
236
237
238
239
240
241 if (dIn.available() == 0)
242 {
243 return new DERTaggedObject(tag & 0x1f, dObj);
244 }
245
246
247
248
249 seq = new DERConstructedSequence();
250
251 seq.addObject(dObj);
252
253 try
254 {
255 for (;;)
256 {
257 dObj = dIn.readObject();
258
259 seq.addObject(dObj);
260 }
261 }
262 catch (EOFException ex)
263 {
264
265 }
266
267 return new DERTaggedObject(false, tag & 0x1f, seq);
268 }
269
270 return new DERUnknownTag(tag, bytes);
271 }
272 }
273
274 public DERObject readObject()
275 throws IOException
276 {
277 int tag = read();
278 if (tag == -1)
279 {
280 throw new EOFException();
281 }
282
283 int length = readLength();
284 byte[] bytes = new byte[length];
285
286 readFully(bytes);
287
288 return buildObject(tag, bytes);
289 }
290 }