1 19 20 package com.maverick.crypto.asn1; 21 22 import java.io.ByteArrayInputStream ; 23 import java.io.ByteArrayOutputStream ; 24 import java.io.EOFException ; 25 import java.io.IOException ; 26 import java.io.InputStream ; 27 import java.util.Vector ; 28 29 35 public class ASN1InputStream 36 extends DERInputStream 37 { 38 private DERObject END_OF_STREAM = new DERObject() { 39 void encode( 40 DEROutputStream out) 41 throws IOException 42 { 43 throw new IOException ("Eeek!"); 44 } 45 46 }; 47 boolean eofFound = false; 48 49 public ASN1InputStream( 50 InputStream is) 51 { 52 super(is); 53 } 54 55 protected int readLength() 56 throws IOException 57 { 58 int length = read(); 59 if (length < 0) 60 { 61 throw new IOException ("EOF found when length expected"); 62 } 63 64 if (length == 0x80) 65 { 66 return -1; } 68 69 if (length > 127) 70 { 71 int size = length & 0x7f; 72 73 length = 0; 74 for (int i = 0; i < size; i++) 75 { 76 int next = read(); 77 78 if (next < 0) 79 { 80 throw new IOException ("EOF found reading length"); 81 } 82 83 length = (length << 8) + next; 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 int len; 96 97 if (left == 0) 98 { 99 return; 100 } 101 102 while ((len = read(bytes, bytes.length - left, left)) > 0) 103 { 104 if ((left -= len) == 0) 105 { 106 return; 107 } 108 } 109 110 if (left != 0) 111 { 112 throw new EOFException ("EOF encountered in middle of object"); 113 } 114 } 115 116 120 protected DERObject buildObject( 121 int tag, 122 byte[] bytes) 123 throws IOException 124 { 125 if ((tag & APPLICATION) != 0) 126 { 127 return new DERApplicationSpecific(tag, bytes); 128 } 129 130 switch (tag) 131 { 132 case NULL: 133 return new DERNull(); 134 case SEQUENCE | CONSTRUCTED: 135 ByteArrayInputStream bIn = new ByteArrayInputStream (bytes); 136 ASN1InputStream aIn = new ASN1InputStream(bIn); 137 ASN1EncodableVector v = new ASN1EncodableVector(); 138 139 DERObject obj = aIn.readObject(); 140 141 while (obj != null) 142 { 143 v.add(obj); 144 obj = aIn.readObject(); 145 } 146 147 return new DERSequence(v); 148 case SET | CONSTRUCTED: 149 bIn = new ByteArrayInputStream (bytes); 150 aIn = new ASN1InputStream(bIn); 151 v = new ASN1EncodableVector(); 152 153 obj = aIn.readObject(); 154 155 while (obj != null) 156 { 157 v.add(obj); 158 obj = aIn.readObject(); 159 } 160 161 return new DERSet(v); 162 case BOOLEAN: 163 return new DERBoolean(bytes); 164 case INTEGER: 165 return new DERInteger(bytes); 166 case ENUMERATED: 167 return new DEREnumerated(bytes); 168 case OBJECT_IDENTIFIER: 169 return new DERObjectIdentifier(bytes); 170 case BIT_STRING: 171 int padBits = bytes[0]; 172 byte[] data = new byte[bytes.length - 1]; 173 174 System.arraycopy(bytes, 1, data, 0, bytes.length - 1); 175 176 return new DERBitString(data, padBits); 177 case UTF8_STRING: 178 return new DERUTF8String(bytes); 179 case PRINTABLE_STRING: 180 return new DERPrintableString(bytes); 181 case IA5_STRING: 182 return new DERIA5String(bytes); 183 case T61_STRING: 184 return new DERT61String(bytes); 185 case VISIBLE_STRING: 186 return new DERVisibleString(bytes); 187 case GENERAL_STRING: 188 return new DERGeneralString(bytes); 189 case UNIVERSAL_STRING: 190 return new DERUniversalString(bytes); 191 case BMP_STRING: 192 return new DERBMPString(bytes); 193 case OCTET_STRING: 194 return new DEROctetString(bytes); 195 case UTC_TIME: 196 return new DERUTCTime(bytes); 197 case GENERALIZED_TIME: 198 return new DERGeneralizedTime(bytes); 199 default: 200 if ((tag & TAGGED) != 0) 204 { 205 int tagNo = tag & 0x1f; 206 207 if (tagNo == 0x1f) 208 { 209 int idx = 0; 210 211 tagNo = 0; 212 213 while ((bytes[idx] & 0x80) != 0) 214 { 215 tagNo |= (bytes[idx++] & 0x7f); 216 tagNo <<= 7; 217 } 218 219 tagNo |= (bytes[idx] & 0x7f); 220 221 byte[] tmp = bytes; 222 223 bytes = new byte[tmp.length - (idx + 1)]; 224 System.arraycopy(tmp, idx + 1, bytes, 0, bytes.length); 225 } 226 227 if (bytes.length == 0) { 229 if ((tag & CONSTRUCTED) == 0) 230 { 231 return new DERTaggedObject(false, tagNo, new DERNull()); 232 } 233 else 234 { 235 return new DERTaggedObject(false, tagNo, new DERSequence()); 236 } 237 } 238 239 if ((tag & CONSTRUCTED) == 0) 243 { 244 return new DERTaggedObject(false, tagNo, new DEROctetString(bytes)); 245 } 246 247 bIn = new ByteArrayInputStream (bytes); 248 aIn = new ASN1InputStream(bIn); 249 250 DEREncodable dObj = aIn.readObject(); 251 252 if (aIn.available() == 0) 257 { 258 return new DERTaggedObject(tagNo, dObj); 259 } 260 261 v = new ASN1EncodableVector(); 265 266 while (dObj != null) 267 { 268 v.add(dObj); 269 dObj = aIn.readObject(); 270 } 271 272 return new DERTaggedObject(false, tagNo, new DERSequence(v)); 273 } 274 275 return new DERUnknownTag(tag, bytes); 276 } 277 } 278 279 282 private byte[] readIndefiniteLengthFully() 283 throws IOException 284 { 285 ByteArrayOutputStream bOut = new ByteArrayOutputStream (); 286 int b, b1; 287 288 b1 = read(); 289 290 while ((b = read()) >= 0) 291 { 292 if (b1 == 0 && b == 0) 293 { 294 break; 295 } 296 297 bOut.write(b1); 298 b1 = b; 299 } 300 301 return bOut.toByteArray(); 302 } 303 304 private BERConstructedOctetString buildConstructedOctetString() 305 throws IOException 306 { 307 Vector octs = new Vector (); 308 309 for (;;) 310 { 311 DERObject o = readObject(); 312 313 if (o == END_OF_STREAM) 314 { 315 break; 316 } 317 318 octs.addElement(o); 319 } 320 321 return new BERConstructedOctetString(octs); 322 } 323 324 public DERObject readObject() 325 throws IOException 326 { 327 int tag = read(); 328 if (tag == -1) 329 { 330 if (eofFound) 331 { 332 throw new EOFException ("attempt to read past end of file."); 333 } 334 335 eofFound = true; 336 337 return null; 338 } 339 340 int length = readLength(); 341 342 if (length < 0) { 344 switch (tag) 345 { 346 case NULL: 347 return new BERNull(); 348 case SEQUENCE | CONSTRUCTED: 349 ASN1EncodableVector v = new ASN1EncodableVector(); 350 351 for (;;) 352 { 353 DERObject obj = readObject(); 354 355 if (obj == END_OF_STREAM) 356 { 357 break; 358 } 359 360 v.add(obj); 361 } 362 return new BERSequence(v); 363 case SET | CONSTRUCTED: 364 v = new ASN1EncodableVector(); 365 366 for (;;) 367 { 368 DERObject obj = readObject(); 369 370 if (obj == END_OF_STREAM) 371 { 372 break; 373 } 374 375 v.add(obj); 376 } 377 return new BERSet(v); 378 case OCTET_STRING | CONSTRUCTED: 379 return buildConstructedOctetString(); 380 default: 381 if ((tag & TAGGED) != 0) 385 { 386 int tagNo = tag & 0x1f; 387 388 if (tagNo == 0x1f) 389 { 390 int b = read(); 391 392 tagNo = 0; 393 394 while ((b >= 0) && ((b & 0x80) != 0)) 395 { 396 tagNo |= (b & 0x7f); 397 tagNo <<= 7; 398 b = read(); 399 } 400 401 tagNo |= (b & 0x7f); 402 } 403 404 if ((tag & CONSTRUCTED) == 0) 408 { 409 byte[] bytes = readIndefiniteLengthFully(); 410 411 return new BERTaggedObject(false, tagNo, new DEROctetString(bytes)); 412 } 413 414 DERObject dObj = readObject(); 418 419 if (dObj == END_OF_STREAM) { 421 return new DERTaggedObject(tagNo); 422 } 423 424 DERObject next = readObject(); 425 426 if (next == END_OF_STREAM) 431 { 432 return new BERTaggedObject(tagNo, dObj); 433 } 434 435 v = new ASN1EncodableVector(); 439 440 v.add(dObj); 441 442 do 443 { 444 v.add(next); 445 next = readObject(); 446 } 447 while (next != END_OF_STREAM); 448 449 return new BERTaggedObject(false, tagNo, new BERSequence(v)); 450 } 451 452 throw new IOException ("unknown BER object encountered"); 453 } 454 } 455 else 456 { 457 if (tag == 0 && length == 0) { 459 return END_OF_STREAM; 460 } 461 462 byte[] bytes = new byte[length]; 463 464 readFully(bytes); 465 466 return buildObject(tag, bytes); 467 } 468 } 469 } 470 | Popular Tags |