1 17 18 package org.apache.geronimo.util.asn1; 19 20 import java.io.ByteArrayInputStream ; 21 import java.io.ByteArrayOutputStream ; 22 import java.io.EOFException ; 23 import java.io.FilterInputStream ; 24 import java.io.IOException ; 25 import java.io.InputStream ; 26 import java.util.Vector ; 27 28 34 public class ASN1InputStream 35 extends FilterInputStream 36 implements DERTags 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 public int hashCode() 46 { 47 return 0; 48 } 49 public boolean equals( 50 Object o) 51 { 52 return o == this; 53 } 54 }; 55 boolean eofFound = false; 56 57 public ASN1InputStream( 58 InputStream is) 59 { 60 super(is); 61 } 62 63 public ASN1InputStream( 64 byte[] input) 65 { 66 super(new ByteArrayInputStream (input)); 67 } 68 69 protected int readLength() 70 throws IOException 71 { 72 int length = read(); 73 if (length < 0) 74 { 75 throw new IOException ("EOF found when length expected"); 76 } 77 78 if (length == 0x80) 79 { 80 return -1; } 82 83 if (length > 127) 84 { 85 int size = length & 0x7f; 86 87 if (size > 4) 88 { 89 throw new IOException ("DER length more than 4 bytes"); 90 } 91 92 length = 0; 93 for (int i = 0; i < size; i++) 94 { 95 int next = read(); 96 97 if (next < 0) 98 { 99 throw new IOException ("EOF found reading length"); 100 } 101 102 length = (length << 8) + next; 103 } 104 105 if (length < 0) 106 { 107 throw new IOException ("corrupted steam - negative length found"); 108 } 109 } 110 111 return length; 112 } 113 114 protected void readFully( 115 byte[] bytes) 116 throws IOException 117 { 118 int left = bytes.length; 119 int len; 120 121 if (left == 0) 122 { 123 return; 124 } 125 126 while ((len = read(bytes, bytes.length - left, left)) > 0) 127 { 128 if ((left -= len) == 0) 129 { 130 return; 131 } 132 } 133 134 if (left != 0) 135 { 136 throw new EOFException ("EOF encountered in middle of object"); 137 } 138 } 139 140 144 protected DERObject buildObject( 145 int tag, 146 byte[] bytes) 147 throws IOException 148 { 149 if ((tag & APPLICATION) != 0) 150 { 151 return new DERApplicationSpecific(tag, bytes); 152 } 153 154 switch (tag) 155 { 156 case NULL: 157 return new DERNull(); 158 case SEQUENCE | CONSTRUCTED: 159 ByteArrayInputStream bIn = new ByteArrayInputStream (bytes); 160 ASN1InputStream aIn = new ASN1InputStream(bIn); 161 ASN1EncodableVector v = new ASN1EncodableVector(); 162 163 DERObject obj = aIn.readObject(); 164 165 while (obj != null) 166 { 167 v.add(obj); 168 obj = aIn.readObject(); 169 } 170 171 return new DERSequence(v); 172 case SET | CONSTRUCTED: 173 bIn = new ByteArrayInputStream (bytes); 174 aIn = new ASN1InputStream(bIn); 175 v = new ASN1EncodableVector(); 176 177 obj = aIn.readObject(); 178 179 while (obj != null) 180 { 181 v.add(obj); 182 obj = aIn.readObject(); 183 } 184 185 return new DERSet(v, false); 186 case BOOLEAN: 187 return new DERBoolean(bytes); 188 case INTEGER: 189 return new DERInteger(bytes); 190 case ENUMERATED: 191 return new DEREnumerated(bytes); 192 case OBJECT_IDENTIFIER: 193 return new DERObjectIdentifier(bytes); 194 case BIT_STRING: 195 int padBits = bytes[0]; 196 byte[] data = new byte[bytes.length - 1]; 197 198 System.arraycopy(bytes, 1, data, 0, bytes.length - 1); 199 200 return new DERBitString(data, padBits); 201 case NUMERIC_STRING: 202 return new DERNumericString(bytes); 203 case UTF8_STRING: 204 return new DERUTF8String(bytes); 205 case PRINTABLE_STRING: 206 return new DERPrintableString(bytes); 207 case IA5_STRING: 208 return new DERIA5String(bytes); 209 case T61_STRING: 210 return new DERT61String(bytes); 211 case VISIBLE_STRING: 212 return new DERVisibleString(bytes); 213 case GENERAL_STRING: 214 return new DERGeneralString(bytes); 215 case UNIVERSAL_STRING: 216 return new DERUniversalString(bytes); 217 case BMP_STRING: 218 return new DERBMPString(bytes); 219 case OCTET_STRING: 220 return new DEROctetString(bytes); 221 case UTC_TIME: 222 return new DERUTCTime(bytes); 223 case GENERALIZED_TIME: 224 return new DERGeneralizedTime(bytes); 225 default: 226 if ((tag & TAGGED) != 0) 230 { 231 int tagNo = tag & 0x1f; 232 233 if (tagNo == 0x1f) 234 { 235 int idx = 0; 236 237 tagNo = 0; 238 239 while ((bytes[idx] & 0x80) != 0) 240 { 241 tagNo |= (bytes[idx++] & 0x7f); 242 tagNo <<= 7; 243 } 244 245 tagNo |= (bytes[idx] & 0x7f); 246 247 byte[] tmp = bytes; 248 249 bytes = new byte[tmp.length - (idx + 1)]; 250 System.arraycopy(tmp, idx + 1, bytes, 0, bytes.length); 251 } 252 253 if (bytes.length == 0) { 255 if ((tag & CONSTRUCTED) == 0) 256 { 257 return new DERTaggedObject(false, tagNo, new DERNull()); 258 } 259 else 260 { 261 return new DERTaggedObject(false, tagNo, new DERSequence()); 262 } 263 } 264 265 if ((tag & CONSTRUCTED) == 0) 269 { 270 return new DERTaggedObject(false, tagNo, new DEROctetString(bytes)); 271 } 272 273 bIn = new ByteArrayInputStream (bytes); 274 aIn = new ASN1InputStream(bIn); 275 276 DEREncodable dObj = aIn.readObject(); 277 278 if (aIn.available() == 0) 283 { 284 return new DERTaggedObject(tagNo, dObj); 285 } 286 287 v = new ASN1EncodableVector(); 291 292 while (dObj != null) 293 { 294 v.add(dObj); 295 dObj = aIn.readObject(); 296 } 297 298 return new DERTaggedObject(false, tagNo, new DERSequence(v)); 299 } 300 301 return new DERUnknownTag(tag, bytes); 302 } 303 } 304 305 308 private byte[] readIndefiniteLengthFully() 309 throws IOException 310 { 311 ByteArrayOutputStream bOut = new ByteArrayOutputStream (); 312 int b, b1; 313 314 b1 = read(); 315 316 while ((b = read()) >= 0) 317 { 318 if (b1 == 0 && b == 0) 319 { 320 break; 321 } 322 323 bOut.write(b1); 324 b1 = b; 325 } 326 327 return bOut.toByteArray(); 328 } 329 330 private BERConstructedOctetString buildConstructedOctetString() 331 throws IOException 332 { 333 Vector octs = new Vector (); 334 335 for (;;) 336 { 337 DERObject o = readObject(); 338 339 if (o == END_OF_STREAM) 340 { 341 break; 342 } 343 344 octs.addElement(o); 345 } 346 347 return new BERConstructedOctetString(octs); 348 } 349 350 public DERObject readObject() 351 throws IOException 352 { 353 int tag = read(); 354 if (tag == -1) 355 { 356 if (eofFound) 357 { 358 throw new EOFException ("attempt to read past end of file."); 359 } 360 361 eofFound = true; 362 363 return null; 364 } 365 366 int length = readLength(); 367 368 if (length < 0) { 370 switch (tag) 371 { 372 case NULL: 373 return new BERNull(); 374 case SEQUENCE | CONSTRUCTED: 375 ASN1EncodableVector v = new ASN1EncodableVector(); 376 377 for (;;) 378 { 379 DERObject obj = readObject(); 380 381 if (obj == END_OF_STREAM) 382 { 383 break; 384 } 385 386 v.add(obj); 387 } 388 return new BERSequence(v); 389 case SET | CONSTRUCTED: 390 v = new ASN1EncodableVector(); 391 392 for (;;) 393 { 394 DERObject obj = readObject(); 395 396 if (obj == END_OF_STREAM) 397 { 398 break; 399 } 400 401 v.add(obj); 402 } 403 return new BERSet(v, false); 404 case OCTET_STRING | CONSTRUCTED: 405 return buildConstructedOctetString(); 406 default: 407 if ((tag & TAGGED) != 0) 411 { 412 int tagNo = tag & 0x1f; 413 414 if (tagNo == 0x1f) 415 { 416 int b = read(); 417 418 tagNo = 0; 419 420 while ((b >= 0) && ((b & 0x80) != 0)) 421 { 422 tagNo |= (b & 0x7f); 423 tagNo <<= 7; 424 b = read(); 425 } 426 427 tagNo |= (b & 0x7f); 428 } 429 430 if ((tag & CONSTRUCTED) == 0) 434 { 435 byte[] bytes = readIndefiniteLengthFully(); 436 437 return new BERTaggedObject(false, tagNo, new DEROctetString(bytes)); 438 } 439 440 DERObject dObj = readObject(); 444 445 if (dObj == END_OF_STREAM) { 447 return new DERTaggedObject(tagNo); 448 } 449 450 DERObject next = readObject(); 451 452 if (next == END_OF_STREAM) 457 { 458 return new BERTaggedObject(tagNo, dObj); 459 } 460 461 v = new ASN1EncodableVector(); 465 466 v.add(dObj); 467 468 do 469 { 470 v.add(next); 471 next = readObject(); 472 } 473 while (next != END_OF_STREAM); 474 475 return new BERTaggedObject(false, tagNo, new BERSequence(v)); 476 } 477 478 throw new IOException ("unknown BER object encountered"); 479 } 480 } 481 else 482 { 483 if (tag == 0 && length == 0) { 485 return END_OF_STREAM; 486 } 487 488 byte[] bytes = new byte[length]; 489 490 readFully(bytes); 491 492 return buildObject(tag, bytes); 493 } 494 } 495 } 496 | Popular Tags |