1 /* 2 * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package sun.security.util; 27 28 import java.io.InputStream; 29 import java.io.IOException; 30 import java.io.EOFException; 31 import java.util.Date; 32 import java.util.Vector; 33 import java.math.BigInteger; 34 import java.io.DataInputStream; 35 36 /** 37 * A DER input stream, used for parsing ASN.1 DER-encoded data such as 38 * that found in X.509 certificates. DER is a subset of BER/1, which has 39 * the advantage that it allows only a single encoding of primitive data. 40 * (High level data such as dates still support many encodings.) That is, 41 * it uses the "Definite" Encoding Rules (DER) not the "Basic" ones (BER). 42 * 43 * <P>Note that, like BER/1, DER streams are streams of explicitly 44 * tagged data values. Accordingly, this programming interface does 45 * not expose any variant of the java.io.InputStream interface, since 46 * that kind of input stream holds untagged data values and using that 47 * I/O model could prevent correct parsing of the DER data. 48 * 49 * <P>At this time, this class supports only a subset of the types of DER 50 * data encodings which are defined. That subset is sufficient for parsing 51 * most X.509 certificates. 52 * 53 * 54 * @author David Brownell 55 * @author Amit Kapoor 56 * @author Hemma Prafullchandra 57 */ 58 59 public class DerInputStream { 60 61 /* 62 * This version only supports fully buffered DER. This is easy to 63 * work with, though if large objects are manipulated DER becomes 64 * awkward to deal with. That's where BER is useful, since BER 65 * handles streaming data relatively well. 66 */ 67 DerInputBuffer buffer; 68 69 /** The DER tag of the value; one of the tag_ constants. */ 70 public byte tag; 71 72 /** 73 * Create a DER input stream from a data buffer. The buffer is not 74 * copied, it is shared. Accordingly, the buffer should be treated 75 * as read-only. 76 * 77 * @param data the buffer from which to create the string (CONSUMED) 78 */ DerInputStream(byte[] data)79 public DerInputStream(byte[] data) throws IOException { 80 init(data, 0, data.length, true); 81 } 82 83 /** 84 * Create a DER input stream from part of a data buffer. 85 * The buffer is not copied, it is shared. Accordingly, the 86 * buffer should be treated as read-only. 87 * 88 * @param data the buffer from which to create the string (CONSUMED) 89 * @param offset the first index of <em>data</em> which will 90 * be read as DER input in the new stream 91 * @param len how long a chunk of the buffer to use, 92 * starting at "offset" 93 */ DerInputStream(byte[] data, int offset, int len)94 public DerInputStream(byte[] data, int offset, int len) throws IOException { 95 init(data, offset, len, true); 96 } 97 98 /** 99 * Create a DER input stream from part of a data buffer with 100 * additional arg to indicate whether to allow constructed 101 * indefinite-length encoding. 102 * The buffer is not copied, it is shared. Accordingly, the 103 * buffer should be treated as read-only. 104 * 105 * @param data the buffer from which to create the string (CONSUMED) 106 * @param offset the first index of <em>data</em> which will 107 * be read as DER input in the new stream 108 * @param len how long a chunk of the buffer to use, 109 * starting at "offset" 110 * @param allowIndefiniteLength whether to allow constructed 111 * indefinite-length encoding 112 */ DerInputStream(byte[] data, int offset, int len, boolean allowIndefiniteLength)113 public DerInputStream(byte[] data, int offset, int len, 114 boolean allowIndefiniteLength) throws IOException { 115 init(data, offset, len, allowIndefiniteLength); 116 } 117 118 /* 119 * private helper routine 120 */ init(byte[] data, int offset, int len, boolean allowIndefiniteLength)121 private void init(byte[] data, int offset, int len, 122 boolean allowIndefiniteLength) throws IOException { 123 if ((offset+2 > data.length) || (offset+len > data.length)) { 124 throw new IOException("Encoding bytes too short"); 125 } 126 // check for indefinite length encoding 127 if (DerIndefLenConverter.isIndefinite(data[offset+1])) { 128 if (!allowIndefiniteLength) { 129 throw new IOException("Indefinite length BER encoding found"); 130 } else { 131 byte[] inData = new byte[len]; 132 System.arraycopy(data, offset, inData, 0, len); 133 134 DerIndefLenConverter derIn = new DerIndefLenConverter(); 135 buffer = new DerInputBuffer(derIn.convert(inData)); 136 } 137 } else 138 buffer = new DerInputBuffer(data, offset, len); 139 buffer.mark(Integer.MAX_VALUE); 140 } 141 DerInputStream(DerInputBuffer buf)142 DerInputStream(DerInputBuffer buf) { 143 buffer = buf; 144 buffer.mark(Integer.MAX_VALUE); 145 } 146 147 /** 148 * Creates a new DER input stream from part of this input stream. 149 * 150 * @param len how long a chunk of the current input stream to use, 151 * starting at the current position. 152 * @param do_skip true if the existing data in the input stream should 153 * be skipped. If this value is false, the next data read 154 * on this stream and the newly created stream will be the 155 * same. 156 */ subStream(int len, boolean do_skip)157 public DerInputStream subStream(int len, boolean do_skip) 158 throws IOException { 159 DerInputBuffer newbuf = buffer.dup(); 160 161 newbuf.truncate(len); 162 if (do_skip) { 163 buffer.skip(len); 164 } 165 return new DerInputStream(newbuf); 166 } 167 168 /** 169 * Return what has been written to this DerInputStream 170 * as a byte array. Useful for debugging. 171 */ toByteArray()172 public byte[] toByteArray() { 173 return buffer.toByteArray(); 174 } 175 176 /* 177 * PRIMITIVES -- these are "universal" ASN.1 simple types. 178 * 179 * INTEGER, ENUMERATED, BIT STRING, OCTET STRING, NULL 180 * OBJECT IDENTIFIER, SEQUENCE (OF), SET (OF) 181 * UTF8String, PrintableString, T61String, IA5String, UTCTime, 182 * GeneralizedTime, BMPString. 183 * Note: UniversalString not supported till encoder is available. 184 */ 185 186 /** 187 * Get an integer from the input stream as an integer. 188 * 189 * @return the integer held in this DER input stream. 190 */ getInteger()191 public int getInteger() throws IOException { 192 if (buffer.read() != DerValue.tag_Integer) { 193 throw new IOException("DER input, Integer tag error"); 194 } 195 return buffer.getInteger(getLength(buffer)); 196 } 197 198 /** 199 * Get a integer from the input stream as a BigInteger object. 200 * 201 * @return the integer held in this DER input stream. 202 */ getBigInteger()203 public BigInteger getBigInteger() throws IOException { 204 if (buffer.read() != DerValue.tag_Integer) { 205 throw new IOException("DER input, Integer tag error"); 206 } 207 return buffer.getBigInteger(getLength(buffer), false); 208 } 209 210 /** 211 * Returns an ASN.1 INTEGER value as a positive BigInteger. 212 * This is just to deal with implementations that incorrectly encode 213 * some values as negative. 214 * 215 * @return the integer held in this DER value as a BigInteger. 216 */ getPositiveBigInteger()217 public BigInteger getPositiveBigInteger() throws IOException { 218 if (buffer.read() != DerValue.tag_Integer) { 219 throw new IOException("DER input, Integer tag error"); 220 } 221 return buffer.getBigInteger(getLength(buffer), true); 222 } 223 224 /** 225 * Get an enumerated from the input stream. 226 * 227 * @return the integer held in this DER input stream. 228 */ getEnumerated()229 public int getEnumerated() throws IOException { 230 if (buffer.read() != DerValue.tag_Enumerated) { 231 throw new IOException("DER input, Enumerated tag error"); 232 } 233 return buffer.getInteger(getLength(buffer)); 234 } 235 236 /** 237 * Get a bit string from the input stream. Padded bits (if any) 238 * will be stripped off before the bit string is returned. 239 */ getBitString()240 public byte[] getBitString() throws IOException { 241 if (buffer.read() != DerValue.tag_BitString) 242 throw new IOException("DER input not an bit string"); 243 244 return buffer.getBitString(getLength(buffer)); 245 } 246 247 /** 248 * Get a bit string from the input stream. The bit string need 249 * not be byte-aligned. 250 */ getUnalignedBitString()251 public BitArray getUnalignedBitString() throws IOException { 252 if (buffer.read() != DerValue.tag_BitString) 253 throw new IOException("DER input not a bit string"); 254 255 int length = getLength(buffer) - 1; 256 257 /* 258 * First byte = number of excess bits in the last octet of the 259 * representation. 260 */ 261 int excessBits = buffer.read(); 262 if (excessBits < 0) { 263 throw new IOException("Unused bits of bit string invalid"); 264 } 265 int validBits = length*8 - excessBits; 266 if (validBits < 0) { 267 throw new IOException("Valid bits of bit string invalid"); 268 } 269 270 byte[] repn = new byte[length]; 271 272 if ((length != 0) && (buffer.read(repn) != length)) { 273 throw new IOException("Short read of DER bit string"); 274 } 275 276 return new BitArray(validBits, repn); 277 } 278 279 /** 280 * Returns an ASN.1 OCTET STRING from the input stream. 281 */ getOctetString()282 public byte[] getOctetString() throws IOException { 283 if (buffer.read() != DerValue.tag_OctetString) 284 throw new IOException("DER input not an octet string"); 285 286 int length = getLength(buffer); 287 byte[] retval = new byte[length]; 288 if ((length != 0) && (buffer.read(retval) != length)) 289 throw new IOException("Short read of DER octet string"); 290 291 return retval; 292 } 293 294 /** 295 * Returns the asked number of bytes from the input stream. 296 */ getBytes(byte[] val)297 public void getBytes(byte[] val) throws IOException { 298 if ((val.length != 0) && (buffer.read(val) != val.length)) { 299 throw new IOException("Short read of DER octet string"); 300 } 301 } 302 303 /** 304 * Reads an encoded null value from the input stream. 305 */ getNull()306 public void getNull() throws IOException { 307 if (buffer.read() != DerValue.tag_Null || buffer.read() != 0) 308 throw new IOException("getNull, bad data"); 309 } 310 311 /** 312 * Reads an X.200 style Object Identifier from the stream. 313 */ getOID()314 public ObjectIdentifier getOID() throws IOException { 315 return new ObjectIdentifier(this); 316 } 317 318 /** 319 * Return a sequence of encoded entities. ASN.1 sequences are 320 * ordered, and they are often used, like a "struct" in C or C++, 321 * to group data values. They may have optional or context 322 * specific values. 323 * 324 * @param startLen guess about how long the sequence will be 325 * (used to initialize an auto-growing data structure) 326 * @return array of the values in the sequence 327 */ 328 // BEGIN Android-changed: Original encoded form needed for APKs parsing/validation. getSequence(int startLen, boolean originalEncodedFormRetained)329 public DerValue[] getSequence(int startLen, 330 boolean originalEncodedFormRetained) throws IOException { 331 tag = (byte)buffer.read(); 332 if (tag != DerValue.tag_Sequence) 333 throw new IOException("Sequence tag error"); 334 return readVector(startLen, originalEncodedFormRetained); 335 } 336 337 /** 338 * Return a sequence of encoded entities. ASN.1 sequences are 339 * ordered, and they are often used, like a "struct" in C or C++, 340 * to group data values. They may have optional or context 341 * specific values. 342 * 343 * @param startLen guess about how long the sequence will be 344 * (used to initialize an auto-growing data structure) 345 * @return array of the values in the sequence 346 */ getSequence(int startLen)347 public DerValue[] getSequence(int startLen) throws IOException { 348 return getSequence( 349 startLen, 350 false); // no need to retain original encoded form 351 } 352 // END Android-changed: Original encoded form needed for APKs parsing/validation. 353 354 /** 355 * Return a set of encoded entities. ASN.1 sets are unordered, 356 * though DER may specify an order for some kinds of sets (such 357 * as the attributes in an X.500 relative distinguished name) 358 * to facilitate binary comparisons of encoded values. 359 * 360 * @param startLen guess about how large the set will be 361 * (used to initialize an auto-growing data structure) 362 * @return array of the values in the sequence 363 */ getSet(int startLen)364 public DerValue[] getSet(int startLen) throws IOException { 365 tag = (byte)buffer.read(); 366 if (tag != DerValue.tag_Set) 367 throw new IOException("Set tag error"); 368 return readVector(startLen); 369 } 370 371 /** 372 * Return a set of encoded entities. ASN.1 sets are unordered, 373 * though DER may specify an order for some kinds of sets (such 374 * as the attributes in an X.500 relative distinguished name) 375 * to facilitate binary comparisons of encoded values. 376 * 377 * @param startLen guess about how large the set will be 378 * (used to initialize an auto-growing data structure) 379 * @param implicit if true tag is assumed implicit. 380 * @return array of the values in the sequence 381 */ getSet(int startLen, boolean implicit)382 public DerValue[] getSet(int startLen, boolean implicit) 383 throws IOException { 384 // BEGIN Android-changed: Original encoded form needed for APKs parsing/validation. 385 return getSet( 386 startLen, 387 implicit, 388 false); // no need to retain original encoded form 389 } 390 getSet(int startLen, boolean implicit, boolean originalEncodedFormRetained)391 public DerValue[] getSet(int startLen, boolean implicit, 392 boolean originalEncodedFormRetained) 393 throws IOException { 394 tag = (byte)buffer.read(); 395 if (!implicit) { 396 if (tag != DerValue.tag_Set) { 397 throw new IOException("Set tag error"); 398 } 399 } 400 return (readVector(startLen, originalEncodedFormRetained)); 401 // END Android-changed: Original encoded form needed for APKs parsing/validation. 402 } 403 404 /* 405 * Read a "vector" of values ... set or sequence have the 406 * same encoding, except for the initial tag, so both use 407 * this same helper routine. 408 */ readVector(int startLen)409 protected DerValue[] readVector(int startLen) throws IOException { 410 // BEGIN Android-changed: Original encoded form needed for APKs parsing/validation. 411 return readVector( 412 startLen, 413 false); // no need to retain original encoded form 414 } 415 416 /* 417 * Read a "vector" of values ... set or sequence have the 418 * same encoding, except for the initial tag, so both use 419 * this same helper routine. 420 */ readVector(int startLen, boolean originalEncodedFormRetained)421 protected DerValue[] readVector(int startLen, 422 boolean originalEncodedFormRetained) throws IOException { 423 // END Android-changed: Original encoded form needed for APKs parsing/validation. 424 DerInputStream newstr; 425 426 byte lenByte = (byte)buffer.read(); 427 int len = getLength(lenByte, buffer); 428 429 if (len == -1) { 430 // indefinite length encoding found 431 int readLen = buffer.available(); 432 int offset = 2; // for tag and length bytes 433 byte[] indefData = new byte[readLen + offset]; 434 indefData[0] = tag; 435 indefData[1] = lenByte; 436 DataInputStream dis = new DataInputStream(buffer); 437 dis.readFully(indefData, offset, readLen); 438 dis.close(); 439 DerIndefLenConverter derIn = new DerIndefLenConverter(); 440 buffer = new DerInputBuffer(derIn.convert(indefData)); 441 if (tag != buffer.read()) 442 throw new IOException("Indefinite length encoding" + 443 " not supported"); 444 len = DerInputStream.getLength(buffer); 445 } 446 447 if (len == 0) 448 // return empty array instead of null, which should be 449 // used only for missing optionals 450 return new DerValue[0]; 451 452 /* 453 * Create a temporary stream from which to read the data, 454 * unless it's not really needed. 455 */ 456 if (buffer.available() == len) 457 newstr = this; 458 else 459 newstr = subStream(len, true); 460 461 /* 462 * Pull values out of the stream. 463 */ 464 Vector<DerValue> vec = new Vector<DerValue>(startLen); 465 DerValue value; 466 467 do { 468 // Android-changed: Original encoded form needed for APKs parsing/validation. 469 value = new DerValue(newstr.buffer, originalEncodedFormRetained); 470 vec.addElement(value); 471 } while (newstr.available() > 0); 472 473 if (newstr.available() != 0) 474 throw new IOException("Extra data at end of vector"); 475 476 /* 477 * Now stick them into the array we're returning. 478 */ 479 int i, max = vec.size(); 480 DerValue[] retval = new DerValue[max]; 481 482 for (i = 0; i < max; i++) 483 retval[i] = vec.elementAt(i); 484 485 return retval; 486 } 487 488 /** 489 * Get a single DER-encoded value from the input stream. 490 * It can often be useful to pull a value from the stream 491 * and defer parsing it. For example, you can pull a nested 492 * sequence out with one call, and only examine its elements 493 * later when you really need to. 494 */ getDerValue()495 public DerValue getDerValue() throws IOException { 496 return new DerValue(buffer); 497 } 498 499 /** 500 * Read a string that was encoded as a UTF8String DER value. 501 */ getUTF8String()502 public String getUTF8String() throws IOException { 503 return readString(DerValue.tag_UTF8String, "UTF-8", "UTF8"); 504 } 505 506 /** 507 * Read a string that was encoded as a PrintableString DER value. 508 */ getPrintableString()509 public String getPrintableString() throws IOException { 510 return readString(DerValue.tag_PrintableString, "Printable", 511 "ASCII"); 512 } 513 514 /** 515 * Read a string that was encoded as a T61String DER value. 516 */ getT61String()517 public String getT61String() throws IOException { 518 /* 519 * Works for common characters between T61 and ASCII. 520 */ 521 return readString(DerValue.tag_T61String, "T61", "ISO-8859-1"); 522 } 523 524 /** 525 * Read a string that was encoded as a IA5tring DER value. 526 */ getIA5String()527 public String getIA5String() throws IOException { 528 return readString(DerValue.tag_IA5String, "IA5", "ASCII"); 529 } 530 531 /** 532 * Read a string that was encoded as a BMPString DER value. 533 */ getBMPString()534 public String getBMPString() throws IOException { 535 return readString(DerValue.tag_BMPString, "BMP", 536 "UnicodeBigUnmarked"); 537 } 538 539 /** 540 * Read a string that was encoded as a GeneralString DER value. 541 */ getGeneralString()542 public String getGeneralString() throws IOException { 543 return readString(DerValue.tag_GeneralString, "General", 544 "ASCII"); 545 } 546 547 /** 548 * Private helper routine to read an encoded string from the input 549 * stream. 550 * @param stringTag the tag for the type of string to read 551 * @param stringName a name to display in error messages 552 * @param enc the encoder to use to interpret the data. Should 553 * correspond to the stringTag above. 554 */ readString(byte stringTag, String stringName, String enc)555 private String readString(byte stringTag, String stringName, 556 String enc) throws IOException { 557 558 if (buffer.read() != stringTag) 559 throw new IOException("DER input not a " + 560 stringName + " string"); 561 562 int length = getLength(buffer); 563 byte[] retval = new byte[length]; 564 if ((length != 0) && (buffer.read(retval) != length)) 565 throw new IOException("Short read of DER " + 566 stringName + " string"); 567 568 return new String(retval, enc); 569 } 570 571 /** 572 * Get a UTC encoded time value from the input stream. 573 */ getUTCTime()574 public Date getUTCTime() throws IOException { 575 if (buffer.read() != DerValue.tag_UtcTime) 576 throw new IOException("DER input, UTCtime tag invalid "); 577 return buffer.getUTCTime(getLength(buffer)); 578 } 579 580 /** 581 * Get a Generalized encoded time value from the input stream. 582 */ getGeneralizedTime()583 public Date getGeneralizedTime() throws IOException { 584 if (buffer.read() != DerValue.tag_GeneralizedTime) 585 throw new IOException("DER input, GeneralizedTime tag invalid "); 586 return buffer.getGeneralizedTime(getLength(buffer)); 587 } 588 589 /* 590 * Get a byte from the input stream. 591 */ 592 // package private getByte()593 int getByte() throws IOException { 594 return (0x00ff & buffer.read()); 595 } 596 peekByte()597 public int peekByte() throws IOException { 598 return buffer.peek(); 599 } 600 601 // package private getLength()602 int getLength() throws IOException { 603 return getLength(buffer); 604 } 605 606 /* 607 * Get a length from the input stream, allowing for at most 32 bits of 608 * encoding to be used. (Not the same as getting a tagged integer!) 609 * 610 * @return the length or -1 if indefinite length found. 611 * @exception IOException on parsing error or unsupported lengths. 612 */ getLength(InputStream in)613 static int getLength(InputStream in) throws IOException { 614 return getLength(in.read(), in); 615 } 616 617 /* 618 * Get a length from the input stream, allowing for at most 32 bits of 619 * encoding to be used. (Not the same as getting a tagged integer!) 620 * 621 * @return the length or -1 if indefinite length found. 622 * @exception IOException on parsing error or unsupported lengths. 623 */ getLength(int lenByte, InputStream in)624 static int getLength(int lenByte, InputStream in) throws IOException { 625 int value, tmp; 626 if (lenByte == -1) { 627 throw new IOException("Short read of DER length"); 628 } 629 630 String mdName = "DerInputStream.getLength(): "; 631 tmp = lenByte; 632 if ((tmp & 0x080) == 0x00) { // short form, 1 byte datum 633 value = tmp; 634 } else { // long form or indefinite 635 tmp &= 0x07f; 636 637 /* 638 * NOTE: tmp == 0 indicates indefinite length encoded data. 639 * tmp > 4 indicates more than 4Gb of data. 640 */ 641 if (tmp == 0) 642 return -1; 643 if (tmp < 0 || tmp > 4) 644 throw new IOException(mdName + "lengthTag=" + tmp + ", " 645 + ((tmp < 0) ? "incorrect DER encoding." : "too big.")); 646 647 value = 0x0ff & in.read(); 648 tmp--; 649 if (value == 0) { 650 // DER requires length value be encoded in minimum number of bytes 651 throw new IOException(mdName + "Redundant length bytes found"); 652 } 653 while (tmp-- > 0) { 654 value <<= 8; 655 value += 0x0ff & in.read(); 656 } 657 if (value < 0) { 658 throw new IOException(mdName + "Invalid length bytes"); 659 } else if (value <= 127) { 660 throw new IOException(mdName + "Should use short form for length"); 661 } 662 } 663 return value; 664 } 665 666 /** 667 * Mark the current position in the buffer, so that 668 * a later call to <code>reset</code> will return here. 669 */ mark(int value)670 public void mark(int value) { buffer.mark(value); } 671 672 673 /** 674 * Return to the position of the last <code>mark</code> 675 * call. A mark is implicitly set at the beginning of 676 * the stream when it is created. 677 */ reset()678 public void reset() { buffer.reset(); } 679 680 681 /** 682 * Returns the number of bytes available for reading. 683 * This is most useful for testing whether the stream is 684 * empty. 685 */ available()686 public int available() { return buffer.available(); } 687 } 688