2002/03/21 01:19:32
[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                 DEROctetString  o1,
52                 DEROctetString  o2)
53                 throws IOException
54         {
55         Vector                  octs = new Vector();
56
57                 if (o1 != null)
58                 {
59             octs.addElement(o1);
60             octs.addElement(o2);
61                 }
62
63                 for (;;)
64                 {
65                         DERObject               o = readObject();
66
67                         if (o == END_OF_STREAM)
68                         {
69                                 break;
70                         }
71
72             octs.addElement(o);
73                 }
74
75                 return new BERConstructedOctetString(octs);
76         }
77
78     public DERObject readObject()
79         throws IOException
80     {
81         int tag = read();
82         if (tag == -1)
83         {
84             throw new EOFException();
85         }
86     
87         int     length = readLength();
88
89         if (length < 0)    // indefinite length method
90         {
91             byte[]  bytes;
92     
93             switch (tag)
94             {
95             case NULL:
96                 return null;
97             case SEQUENCE | CONSTRUCTED:
98                 BERConstructedSequence  seq = new BERConstructedSequence();
99     
100                                 for (;;)
101                                 {
102                                         DERObject   obj = readObject();
103
104                                         if (obj == END_OF_STREAM)
105                                         {
106                                                 break;
107                                         }
108
109                                         seq.addObject(obj);
110                                 }
111                                 return seq;
112             case OCTET_STRING | CONSTRUCTED:
113                                 return buildConstructedOctetString(null, null);
114             default:
115                 if ((tag & (TAGGED | CONSTRUCTED)) != 0)  
116                 {
117                                         // with tagged object tag number is bottom 4 bits
118                     BERTaggedObject tagObj = new BERTaggedObject(tag & 0x0f, readObject());
119                                         DERObject               o = readObject();
120
121                                         if (o == END_OF_STREAM)
122                                         {
123                                                 return tagObj;
124                                         }
125                                         else if (o instanceof DEROctetString
126                                                         && tagObj.getObject() instanceof DEROctetString)
127                                         {
128                                                 //
129                                                 // it's an implicit object - mark it as so...
130                                                 //
131                                                 tagObj = new BERTaggedObject(false, tag & 0x0f, 
132                                                                                 buildConstructedOctetString((DEROctetString)tagObj.getObject(), (DEROctetString)o));
133
134                                                 return tagObj;
135                                         }
136
137                                         throw new IOException("truncated tagged object");
138                 }
139     
140                 bytes = readIndefiniteLengthFully();
141
142                 return buildObject(tag, bytes);
143             }
144         }
145         else
146         {
147             if (tag == 0 && length == 0)    // end of contents marker.
148             {
149                 return END_OF_STREAM;
150             }
151
152             byte[]  bytes = new byte[length];
153     
154             readFully(bytes);
155     
156                         return buildObject(tag, bytes);
157         }
158     }
159 }