View Javadoc

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;      // indefinite-length encoding
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             // with tagged object tag number is bottom 5 bits
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)        // empty tag!
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                 // simple type - implicit... return an octet string
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                 // explicitly tagged (probably!) - if it isn't we'd have to
239                 // tell from the context
240                 //
241                 if (dIn.available() == 0)
242                 {
243                     return new DERTaggedObject(tag & 0x1f, dObj);
244                 }
245 
246                 //
247                 // another implicit object, we'll create a sequence...
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                     // ignore --
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 }