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