001: package org.bouncycastle.asn1;
002:
003: import java.io.ByteArrayInputStream;
004: import java.io.EOFException;
005: import java.io.FilterInputStream;
006: import java.io.IOException;
007: import java.io.InputStream;
008:
009: /**
010: * Don't use this class. It will eventually disappear, use ASN1InputStream.
011: * <br>
012: * This class is scheduled for removal.
013: * @deprecated use ASN1InputStream
014: */
015: public class DERInputStream extends FilterInputStream implements
016: DERTags {
017: /**
018: * @deprecated use ASN1InputStream
019: */
020: public DERInputStream(InputStream is) {
021: super (is);
022: }
023:
024: protected int readLength() throws IOException {
025: int length = read();
026: if (length < 0) {
027: throw new IOException("EOF found when length expected");
028: }
029:
030: if (length == 0x80) {
031: return -1; // indefinite-length encoding
032: }
033:
034: if (length > 127) {
035: int size = length & 0x7f;
036:
037: if (size > 4) {
038: throw new IOException("DER length more than 4 bytes");
039: }
040:
041: length = 0;
042: for (int i = 0; i < size; i++) {
043: int next = read();
044:
045: if (next < 0) {
046: throw new IOException("EOF found reading length");
047: }
048:
049: length = (length << 8) + next;
050: }
051:
052: if (length < 0) {
053: throw new IOException(
054: "corrupted stream - negative length found");
055: }
056: }
057:
058: return length;
059: }
060:
061: protected void readFully(byte[] bytes) throws IOException {
062: int left = bytes.length;
063:
064: if (left == 0) {
065: return;
066: }
067:
068: while (left > 0) {
069: int l = read(bytes, bytes.length - left, left);
070:
071: if (l < 0) {
072: throw new EOFException("unexpected end of stream");
073: }
074:
075: left -= l;
076: }
077: }
078:
079: /**
080: * build an object given its tag and a byte stream to construct it
081: * from.
082: */
083: protected DERObject buildObject(int tag, byte[] bytes)
084: throws IOException {
085: switch (tag) {
086: case NULL:
087: return null;
088: case SEQUENCE | CONSTRUCTED:
089: ByteArrayInputStream bIn = new ByteArrayInputStream(bytes);
090: BERInputStream dIn = new BERInputStream(bIn);
091: DERConstructedSequence seq = new DERConstructedSequence();
092:
093: try {
094: for (;;) {
095: DERObject obj = dIn.readObject();
096:
097: seq.addObject(obj);
098: }
099: } catch (EOFException ex) {
100: return seq;
101: }
102: case SET | CONSTRUCTED:
103: bIn = new ByteArrayInputStream(bytes);
104: dIn = new BERInputStream(bIn);
105:
106: ASN1EncodableVector v = new ASN1EncodableVector();
107:
108: try {
109: for (;;) {
110: DERObject obj = dIn.readObject();
111:
112: v.add(obj);
113: }
114: } catch (EOFException ex) {
115: return new DERConstructedSet(v);
116: }
117: case BOOLEAN:
118: return new DERBoolean(bytes);
119: case INTEGER:
120: return new DERInteger(bytes);
121: case ENUMERATED:
122: return new DEREnumerated(bytes);
123: case OBJECT_IDENTIFIER:
124: return new DERObjectIdentifier(bytes);
125: case BIT_STRING:
126: int padBits = bytes[0];
127: byte[] data = new byte[bytes.length - 1];
128:
129: System.arraycopy(bytes, 1, data, 0, bytes.length - 1);
130:
131: return new DERBitString(data, padBits);
132: case UTF8_STRING:
133: return new DERUTF8String(bytes);
134: case PRINTABLE_STRING:
135: return new DERPrintableString(bytes);
136: case IA5_STRING:
137: return new DERIA5String(bytes);
138: case T61_STRING:
139: return new DERT61String(bytes);
140: case VISIBLE_STRING:
141: return new DERVisibleString(bytes);
142: case UNIVERSAL_STRING:
143: return new DERUniversalString(bytes);
144: case GENERAL_STRING:
145: return new DERGeneralString(bytes);
146: case BMP_STRING:
147: return new DERBMPString(bytes);
148: case OCTET_STRING:
149: return new DEROctetString(bytes);
150: case UTC_TIME:
151: return new DERUTCTime(bytes);
152: case GENERALIZED_TIME:
153: return new DERGeneralizedTime(bytes);
154: default:
155: //
156: // with tagged object tag number is bottom 5 bits
157: //
158: if ((tag & TAGGED) != 0) {
159: if ((tag & 0x1f) == 0x1f) {
160: throw new IOException(
161: "unsupported high tag encountered");
162: }
163:
164: if (bytes.length == 0) // empty tag!
165: {
166: if ((tag & CONSTRUCTED) == 0) {
167: return new DERTaggedObject(false, tag & 0x1f,
168: new DERNull());
169: } else {
170: return new DERTaggedObject(false, tag & 0x1f,
171: new DERConstructedSequence());
172: }
173: }
174:
175: //
176: // simple type - implicit... return an octet string
177: //
178: if ((tag & CONSTRUCTED) == 0) {
179: return new DERTaggedObject(false, tag & 0x1f,
180: new DEROctetString(bytes));
181: }
182:
183: bIn = new ByteArrayInputStream(bytes);
184: dIn = new BERInputStream(bIn);
185:
186: DEREncodable dObj = dIn.readObject();
187:
188: //
189: // explicitly tagged (probably!) - if it isn't we'd have to
190: // tell from the context
191: //
192: if (dIn.available() == 0) {
193: return new DERTaggedObject(tag & 0x1f, dObj);
194: }
195:
196: //
197: // another implicit object, we'll create a sequence...
198: //
199: seq = new DERConstructedSequence();
200:
201: seq.addObject(dObj);
202:
203: try {
204: for (;;) {
205: dObj = dIn.readObject();
206:
207: seq.addObject(dObj);
208: }
209: } catch (EOFException ex) {
210: // ignore --
211: }
212:
213: return new DERTaggedObject(false, tag & 0x1f, seq);
214: }
215:
216: return new DERUnknownTag(tag, bytes);
217: }
218: }
219:
220: public DERObject readObject() throws IOException {
221: int tag = read();
222: if (tag == -1) {
223: throw new EOFException();
224: }
225:
226: int length = readLength();
227: byte[] bytes = new byte[length];
228:
229: readFully(bytes);
230:
231: return buildObject(tag, bytes);
232: }
233: }
|