1 package org.gudy.bouncycastle.asn1; 2 3 import java.io.ByteArrayInputStream; 4 import java.io.EOFException; 5 import java.io.FilterInputStream; 6 import java.io.IOException; 7 import java.io.InputStream; 8 9 /** 10 * Don't use this class. It will eventually disappear, use ASN1InputStream. 11 * <br> 12 * This class is scheduled for removal. 13 * @deprecated use ASN1InputStream 14 */ 15 public class DERInputStream 16 extends FilterInputStream implements DERTags 17 { 18 /** 19 * @deprecated use ASN1InputStream 20 */ DERInputStream( InputStream is)21 public DERInputStream( 22 InputStream is) 23 { 24 super(is); 25 } 26 readLength()27 protected int readLength() 28 throws IOException 29 { 30 int length = read(); 31 if (length < 0) 32 { 33 throw new IOException("EOF found when length expected"); 34 } 35 36 if (length == 0x80) 37 { 38 return -1; // indefinite-length encoding 39 } 40 41 if (length > 127) 42 { 43 int size = length & 0x7f; 44 45 if (size > 4) 46 { 47 throw new IOException("DER length more than 4 bytes"); 48 } 49 50 length = 0; 51 for (int i = 0; i < size; i++) 52 { 53 int next = read(); 54 55 if (next < 0) 56 { 57 throw new IOException("EOF found reading length"); 58 } 59 60 length = (length << 8) + next; 61 } 62 63 if (length < 0) 64 { 65 throw new IOException("corrupted stream - negative length found"); 66 } 67 } 68 69 return length; 70 } 71 readFully( byte[] bytes)72 protected void readFully( 73 byte[] bytes) 74 throws IOException 75 { 76 int left = bytes.length; 77 78 if (left == 0) 79 { 80 return; 81 } 82 83 while (left > 0) 84 { 85 int l = read(bytes, bytes.length - left, left); 86 87 if (l < 0) 88 { 89 throw new EOFException("unexpected end of stream"); 90 } 91 92 left -= l; 93 } 94 } 95 96 /** 97 * build an object given its tag and a byte stream to construct it 98 * from. 99 */ buildObject( int tag, byte[] bytes)100 protected DERObject buildObject( 101 int tag, 102 byte[] bytes) 103 throws IOException 104 { 105 switch (tag) 106 { 107 case NULL: 108 return null; 109 case SEQUENCE | CONSTRUCTED: 110 ByteArrayInputStream bIn = new ByteArrayInputStream(bytes); 111 BERInputStream dIn = new BERInputStream(bIn); 112 DERConstructedSequence seq = new DERConstructedSequence(); 113 114 try 115 { 116 for (;;) 117 { 118 DERObject obj = dIn.readObject(); 119 120 seq.addObject(obj); 121 } 122 } 123 catch (EOFException ex) 124 { 125 return seq; 126 } 127 case SET | CONSTRUCTED: 128 bIn = new ByteArrayInputStream(bytes); 129 dIn = new BERInputStream(bIn); 130 131 ASN1EncodableVector v = new ASN1EncodableVector(); 132 133 try 134 { 135 for (;;) 136 { 137 DERObject obj = dIn.readObject(); 138 139 v.add(obj); 140 } 141 } 142 catch (EOFException ex) 143 { 144 return new DERConstructedSet(v); 145 } 146 case BOOLEAN: 147 return new DERBoolean(bytes); 148 case INTEGER: 149 return new DERInteger(bytes); 150 case ENUMERATED: 151 return new DEREnumerated(bytes); 152 case OBJECT_IDENTIFIER: 153 return new DERObjectIdentifier(bytes); 154 case BIT_STRING: 155 int padBits = bytes[0]; 156 byte[] data = new byte[bytes.length - 1]; 157 158 System.arraycopy(bytes, 1, data, 0, bytes.length - 1); 159 160 return new DERBitString(data, padBits); 161 case UTF8_STRING: 162 return new DERUTF8String(bytes); 163 case PRINTABLE_STRING: 164 return new DERPrintableString(bytes); 165 case IA5_STRING: 166 return new DERIA5String(bytes); 167 case T61_STRING: 168 return new DERT61String(bytes); 169 case VISIBLE_STRING: 170 return new DERVisibleString(bytes); 171 case UNIVERSAL_STRING: 172 return new DERUniversalString(bytes); 173 case GENERAL_STRING: 174 return new DERGeneralString(bytes); 175 case BMP_STRING: 176 return new DERBMPString(bytes); 177 case OCTET_STRING: 178 return new DEROctetString(bytes); 179 case UTC_TIME: 180 return new DERUTCTime(bytes); 181 case GENERALIZED_TIME: 182 return new DERGeneralizedTime(bytes); 183 default: 184 // 185 // with tagged object tag number is bottom 5 bits 186 // 187 if ((tag & TAGGED) != 0) 188 { 189 if ((tag & 0x1f) == 0x1f) 190 { 191 throw new IOException("unsupported high tag encountered"); 192 } 193 194 if (bytes.length == 0) // empty tag! 195 { 196 if ((tag & CONSTRUCTED) == 0) 197 { 198 return new DERTaggedObject(false, tag & 0x1f, new DERNull()); 199 } 200 else 201 { 202 return new DERTaggedObject(false, tag & 0x1f, new DERConstructedSequence()); 203 } 204 } 205 206 // 207 // simple type - implicit... return an octet string 208 // 209 if ((tag & CONSTRUCTED) == 0) 210 { 211 return new DERTaggedObject(false, tag & 0x1f, new DEROctetString(bytes)); 212 } 213 214 bIn = new ByteArrayInputStream(bytes); 215 dIn = new BERInputStream(bIn); 216 217 DEREncodable dObj = dIn.readObject(); 218 219 // 220 // explicitly tagged (probably!) - if it isn't we'd have to 221 // tell from the context 222 // 223 if (dIn.available() == 0) 224 { 225 return new DERTaggedObject(tag & 0x1f, dObj); 226 } 227 228 // 229 // another implicit object, we'll create a sequence... 230 // 231 seq = new DERConstructedSequence(); 232 233 seq.addObject(dObj); 234 235 try 236 { 237 for (;;) 238 { 239 dObj = dIn.readObject(); 240 241 seq.addObject(dObj); 242 } 243 } 244 catch (EOFException ex) 245 { 246 // ignore -- 247 } 248 249 return new DERTaggedObject(false, tag & 0x1f, seq); 250 } 251 252 return new DERUnknownTag(tag, bytes); 253 } 254 } 255 readObject()256 public DERObject readObject() 257 throws IOException 258 { 259 int tag = read(); 260 if (tag == -1) 261 { 262 throw new EOFException(); 263 } 264 265 int length = readLength(); 266 byte[] bytes = new byte[length]; 267 268 readFully(bytes); 269 270 return buildObject(tag, bytes); 271 } 272 } 273