151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/* 27b63247eb7ae2638740bd13f370bdcf9d3603407Przemyslaw Szczepaniak * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved. 351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is free software; you can redistribute it and/or modify it 651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * under the terms of the GNU General Public License version 2 only, as 751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * published by the Free Software Foundation. Oracle designates this 851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * particular file as subject to the "Classpath" exception as provided 951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * by Oracle in the LICENSE file that accompanied this code. 1051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 1151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is distributed in the hope that it will be useful, but WITHOUT 1251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * version 2 for more details (a copy is included in the LICENSE file that 1551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * accompanied this code). 1651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 1751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * You should have received a copy of the GNU General Public License version 1851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 2 along with this work; if not, write to the Free Software Foundation, 1951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 2151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 2251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * or visit www.oracle.com if you need additional information or have any 2351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * questions. 2451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 2551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 2651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskipackage sun.security.util; 2751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 2851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.io.InputStream; 2951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.io.IOException; 3051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.io.EOFException; 3151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.Date; 3251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.Vector; 3351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.math.BigInteger; 3451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.io.DataInputStream; 3551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 3651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/** 3751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * A DER input stream, used for parsing ASN.1 DER-encoded data such as 3851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * that found in X.509 certificates. DER is a subset of BER/1, which has 3951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the advantage that it allows only a single encoding of primitive data. 4051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * (High level data such as dates still support many encodings.) That is, 4151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * it uses the "Definite" Encoding Rules (DER) not the "Basic" ones (BER). 4251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 4351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <P>Note that, like BER/1, DER streams are streams of explicitly 4451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * tagged data values. Accordingly, this programming interface does 4551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * not expose any variant of the java.io.InputStream interface, since 4651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * that kind of input stream holds untagged data values and using that 4751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * I/O model could prevent correct parsing of the DER data. 4851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 4951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <P>At this time, this class supports only a subset of the types of DER 5051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * data encodings which are defined. That subset is sufficient for parsing 5151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * most X.509 certificates. 5251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 5351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 5451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @author David Brownell 5551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @author Amit Kapoor 5651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @author Hemma Prafullchandra 5751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 5851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 5951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskipublic class DerInputStream { 6051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 6151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* 6251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This version only supports fully buffered DER. This is easy to 6351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * work with, though if large objects are manipulated DER becomes 6451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * awkward to deal with. That's where BER is useful, since BER 6551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * handles streaming data relatively well. 6651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 6751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski DerInputBuffer buffer; 6851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 6951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** The DER tag of the value; one of the tag_ constants. */ 7051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public byte tag; 7151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 7251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 7351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Create a DER input stream from a data buffer. The buffer is not 7451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * copied, it is shared. Accordingly, the buffer should be treated 7551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * as read-only. 7651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 7751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param data the buffer from which to create the string (CONSUMED) 7851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 7951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public DerInputStream(byte[] data) throws IOException { 807b63247eb7ae2638740bd13f370bdcf9d3603407Przemyslaw Szczepaniak init(data, 0, data.length, true); 8151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 8251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 8351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 8451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Create a DER input stream from part of a data buffer. 8551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The buffer is not copied, it is shared. Accordingly, the 8651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * buffer should be treated as read-only. 8751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 8851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param data the buffer from which to create the string (CONSUMED) 8951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param offset the first index of <em>data</em> which will 9051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * be read as DER input in the new stream 9151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param len how long a chunk of the buffer to use, 9251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * starting at "offset" 9351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 9451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public DerInputStream(byte[] data, int offset, int len) throws IOException { 957b63247eb7ae2638740bd13f370bdcf9d3603407Przemyslaw Szczepaniak init(data, offset, len, true); 967b63247eb7ae2638740bd13f370bdcf9d3603407Przemyslaw Szczepaniak } 977b63247eb7ae2638740bd13f370bdcf9d3603407Przemyslaw Szczepaniak 987b63247eb7ae2638740bd13f370bdcf9d3603407Przemyslaw Szczepaniak /** 997b63247eb7ae2638740bd13f370bdcf9d3603407Przemyslaw Szczepaniak * Create a DER input stream from part of a data buffer with 1007b63247eb7ae2638740bd13f370bdcf9d3603407Przemyslaw Szczepaniak * additional arg to indicate whether to allow constructed 1017b63247eb7ae2638740bd13f370bdcf9d3603407Przemyslaw Szczepaniak * indefinite-length encoding. 1027b63247eb7ae2638740bd13f370bdcf9d3603407Przemyslaw Szczepaniak * The buffer is not copied, it is shared. Accordingly, the 1037b63247eb7ae2638740bd13f370bdcf9d3603407Przemyslaw Szczepaniak * buffer should be treated as read-only. 1047b63247eb7ae2638740bd13f370bdcf9d3603407Przemyslaw Szczepaniak * 1057b63247eb7ae2638740bd13f370bdcf9d3603407Przemyslaw Szczepaniak * @param data the buffer from which to create the string (CONSUMED) 1067b63247eb7ae2638740bd13f370bdcf9d3603407Przemyslaw Szczepaniak * @param offset the first index of <em>data</em> which will 1077b63247eb7ae2638740bd13f370bdcf9d3603407Przemyslaw Szczepaniak * be read as DER input in the new stream 1087b63247eb7ae2638740bd13f370bdcf9d3603407Przemyslaw Szczepaniak * @param len how long a chunk of the buffer to use, 1097b63247eb7ae2638740bd13f370bdcf9d3603407Przemyslaw Szczepaniak * starting at "offset" 1107b63247eb7ae2638740bd13f370bdcf9d3603407Przemyslaw Szczepaniak * @param allowIndefiniteLength whether to allow constructed 1117b63247eb7ae2638740bd13f370bdcf9d3603407Przemyslaw Szczepaniak * indefinite-length encoding 1127b63247eb7ae2638740bd13f370bdcf9d3603407Przemyslaw Szczepaniak */ 1137b63247eb7ae2638740bd13f370bdcf9d3603407Przemyslaw Szczepaniak public DerInputStream(byte[] data, int offset, int len, 1147b63247eb7ae2638740bd13f370bdcf9d3603407Przemyslaw Szczepaniak boolean allowIndefiniteLength) throws IOException { 1157b63247eb7ae2638740bd13f370bdcf9d3603407Przemyslaw Szczepaniak init(data, offset, len, allowIndefiniteLength); 11651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 11751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 11851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* 11951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * private helper routine 12051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 1217b63247eb7ae2638740bd13f370bdcf9d3603407Przemyslaw Szczepaniak private void init(byte[] data, int offset, int len, 1227b63247eb7ae2638740bd13f370bdcf9d3603407Przemyslaw Szczepaniak boolean allowIndefiniteLength) throws IOException { 12351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if ((offset+2 > data.length) || (offset+len > data.length)) { 12451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("Encoding bytes too short"); 12551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 12651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // check for indefinite length encoding 12751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (DerIndefLenConverter.isIndefinite(data[offset+1])) { 1287b63247eb7ae2638740bd13f370bdcf9d3603407Przemyslaw Szczepaniak if (!allowIndefiniteLength) { 1297b63247eb7ae2638740bd13f370bdcf9d3603407Przemyslaw Szczepaniak throw new IOException("Indefinite length BER encoding found"); 1307b63247eb7ae2638740bd13f370bdcf9d3603407Przemyslaw Szczepaniak } else { 1317b63247eb7ae2638740bd13f370bdcf9d3603407Przemyslaw Szczepaniak byte[] inData = new byte[len]; 1327b63247eb7ae2638740bd13f370bdcf9d3603407Przemyslaw Szczepaniak System.arraycopy(data, offset, inData, 0, len); 1337b63247eb7ae2638740bd13f370bdcf9d3603407Przemyslaw Szczepaniak 1347b63247eb7ae2638740bd13f370bdcf9d3603407Przemyslaw Szczepaniak DerIndefLenConverter derIn = new DerIndefLenConverter(); 1357b63247eb7ae2638740bd13f370bdcf9d3603407Przemyslaw Szczepaniak buffer = new DerInputBuffer(derIn.convert(inData)); 1367b63247eb7ae2638740bd13f370bdcf9d3603407Przemyslaw Szczepaniak } 13751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else 13851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski buffer = new DerInputBuffer(data, offset, len); 13951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski buffer.mark(Integer.MAX_VALUE); 14051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 14151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 14251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski DerInputStream(DerInputBuffer buf) { 14351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski buffer = buf; 14451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski buffer.mark(Integer.MAX_VALUE); 14551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 14651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 14751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 14851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Creates a new DER input stream from part of this input stream. 14951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 15051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param len how long a chunk of the current input stream to use, 15151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * starting at the current position. 15251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param do_skip true if the existing data in the input stream should 15351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * be skipped. If this value is false, the next data read 15451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * on this stream and the newly created stream will be the 15551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * same. 15651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 15751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public DerInputStream subStream(int len, boolean do_skip) 15851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throws IOException { 15951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski DerInputBuffer newbuf = buffer.dup(); 16051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 16151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski newbuf.truncate(len); 16251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (do_skip) { 16351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski buffer.skip(len); 16451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 16551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return new DerInputStream(newbuf); 16651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 16751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 16851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 16951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Return what has been written to this DerInputStream 17051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * as a byte array. Useful for debugging. 17151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 17251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public byte[] toByteArray() { 17351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return buffer.toByteArray(); 17451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 17551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 17651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* 17751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * PRIMITIVES -- these are "universal" ASN.1 simple types. 17851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 17951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * INTEGER, ENUMERATED, BIT STRING, OCTET STRING, NULL 18051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * OBJECT IDENTIFIER, SEQUENCE (OF), SET (OF) 18151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * UTF8String, PrintableString, T61String, IA5String, UTCTime, 18251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * GeneralizedTime, BMPString. 18351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Note: UniversalString not supported till encoder is available. 18451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 18551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 18651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 18751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Get an integer from the input stream as an integer. 18851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 18951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return the integer held in this DER input stream. 19051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 19151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public int getInteger() throws IOException { 19251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (buffer.read() != DerValue.tag_Integer) { 19351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("DER input, Integer tag error"); 19451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 19551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return buffer.getInteger(getLength(buffer)); 19651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 19751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 19851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 19951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Get a integer from the input stream as a BigInteger object. 20051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 20151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return the integer held in this DER input stream. 20251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 20351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public BigInteger getBigInteger() throws IOException { 20451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (buffer.read() != DerValue.tag_Integer) { 20551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("DER input, Integer tag error"); 20651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 20751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return buffer.getBigInteger(getLength(buffer), false); 20851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 20951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 21051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 21151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Returns an ASN.1 INTEGER value as a positive BigInteger. 21251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This is just to deal with implementations that incorrectly encode 21351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * some values as negative. 21451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 21551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return the integer held in this DER value as a BigInteger. 21651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 21751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public BigInteger getPositiveBigInteger() throws IOException { 21851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (buffer.read() != DerValue.tag_Integer) { 21951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("DER input, Integer tag error"); 22051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 22151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return buffer.getBigInteger(getLength(buffer), true); 22251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 22351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 22451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 22551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Get an enumerated from the input stream. 22651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 22751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return the integer held in this DER input stream. 22851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 22951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public int getEnumerated() throws IOException { 23051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (buffer.read() != DerValue.tag_Enumerated) { 23151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("DER input, Enumerated tag error"); 23251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 23351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return buffer.getInteger(getLength(buffer)); 23451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 23551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 23651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 23751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Get a bit string from the input stream. Padded bits (if any) 23851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * will be stripped off before the bit string is returned. 23951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 24051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public byte[] getBitString() throws IOException { 24151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (buffer.read() != DerValue.tag_BitString) 24251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("DER input not an bit string"); 24351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 24451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return buffer.getBitString(getLength(buffer)); 24551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 24651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 24751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 24851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Get a bit string from the input stream. The bit string need 24951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * not be byte-aligned. 25051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 25151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public BitArray getUnalignedBitString() throws IOException { 25251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (buffer.read() != DerValue.tag_BitString) 25351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("DER input not a bit string"); 25451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 25551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int length = getLength(buffer) - 1; 25651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 25751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* 25851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * First byte = number of excess bits in the last octet of the 25951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * representation. 26051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 2617b63247eb7ae2638740bd13f370bdcf9d3603407Przemyslaw Szczepaniak int excessBits = buffer.read(); 2627b63247eb7ae2638740bd13f370bdcf9d3603407Przemyslaw Szczepaniak if (excessBits < 0) { 2637b63247eb7ae2638740bd13f370bdcf9d3603407Przemyslaw Szczepaniak throw new IOException("Unused bits of bit string invalid"); 2647b63247eb7ae2638740bd13f370bdcf9d3603407Przemyslaw Szczepaniak } 2657b63247eb7ae2638740bd13f370bdcf9d3603407Przemyslaw Szczepaniak int validBits = length*8 - excessBits; 2667b63247eb7ae2638740bd13f370bdcf9d3603407Przemyslaw Szczepaniak if (validBits < 0) { 2677b63247eb7ae2638740bd13f370bdcf9d3603407Przemyslaw Szczepaniak throw new IOException("Valid bits of bit string invalid"); 2687b63247eb7ae2638740bd13f370bdcf9d3603407Przemyslaw Szczepaniak } 26951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 27051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski byte[] repn = new byte[length]; 27151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 2727b63247eb7ae2638740bd13f370bdcf9d3603407Przemyslaw Szczepaniak if ((length != 0) && (buffer.read(repn) != length)) { 2737b63247eb7ae2638740bd13f370bdcf9d3603407Przemyslaw Szczepaniak throw new IOException("Short read of DER bit string"); 2747b63247eb7ae2638740bd13f370bdcf9d3603407Przemyslaw Szczepaniak } 2757b63247eb7ae2638740bd13f370bdcf9d3603407Przemyslaw Szczepaniak 27651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return new BitArray(validBits, repn); 27751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 27851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 27951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 28051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Returns an ASN.1 OCTET STRING from the input stream. 28151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 28251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public byte[] getOctetString() throws IOException { 28351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (buffer.read() != DerValue.tag_OctetString) 28451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("DER input not an octet string"); 28551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 28651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int length = getLength(buffer); 28751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski byte[] retval = new byte[length]; 28851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if ((length != 0) && (buffer.read(retval) != length)) 2897b63247eb7ae2638740bd13f370bdcf9d3603407Przemyslaw Szczepaniak throw new IOException("Short read of DER octet string"); 29051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 29151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return retval; 29251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 29351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 29451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 29551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Returns the asked number of bytes from the input stream. 29651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 29751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void getBytes(byte[] val) throws IOException { 29851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if ((val.length != 0) && (buffer.read(val) != val.length)) { 2997b63247eb7ae2638740bd13f370bdcf9d3603407Przemyslaw Szczepaniak throw new IOException("Short read of DER octet string"); 30051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 30151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 30251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 30351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 30451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Reads an encoded null value from the input stream. 30551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 30651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void getNull() throws IOException { 30751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (buffer.read() != DerValue.tag_Null || buffer.read() != 0) 30851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("getNull, bad data"); 30951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 31051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 31151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 31251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Reads an X.200 style Object Identifier from the stream. 31351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 31451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public ObjectIdentifier getOID() throws IOException { 31551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return new ObjectIdentifier(this); 31651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 31751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 31851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 31951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Return a sequence of encoded entities. ASN.1 sequences are 32051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * ordered, and they are often used, like a "struct" in C or C++, 32151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * to group data values. They may have optional or context 32251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * specific values. 32351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 32451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param startLen guess about how long the sequence will be 32551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * (used to initialize an auto-growing data structure) 32651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return array of the values in the sequence 32751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 328f5a241465eef5d8b4edaaeccc63680e1ea65bb18Przemyslaw Szczepaniak // BEGIN Android-changed: Original encoded form needed for APKs parsing/validation 3297a5b72d23c5b24e627ae09a7ab04f58cb1090d2bAlex Klyubin public DerValue[] getSequence(int startLen, 3307a5b72d23c5b24e627ae09a7ab04f58cb1090d2bAlex Klyubin boolean originalEncodedFormRetained) throws IOException { 33151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski tag = (byte)buffer.read(); 33251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (tag != DerValue.tag_Sequence) 33351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("Sequence tag error"); 3347a5b72d23c5b24e627ae09a7ab04f58cb1090d2bAlex Klyubin return readVector(startLen, originalEncodedFormRetained); 3357a5b72d23c5b24e627ae09a7ab04f58cb1090d2bAlex Klyubin } 3367a5b72d23c5b24e627ae09a7ab04f58cb1090d2bAlex Klyubin 3377a5b72d23c5b24e627ae09a7ab04f58cb1090d2bAlex Klyubin /** 3387a5b72d23c5b24e627ae09a7ab04f58cb1090d2bAlex Klyubin * Return a sequence of encoded entities. ASN.1 sequences are 3397a5b72d23c5b24e627ae09a7ab04f58cb1090d2bAlex Klyubin * ordered, and they are often used, like a "struct" in C or C++, 3407a5b72d23c5b24e627ae09a7ab04f58cb1090d2bAlex Klyubin * to group data values. They may have optional or context 3417a5b72d23c5b24e627ae09a7ab04f58cb1090d2bAlex Klyubin * specific values. 3427a5b72d23c5b24e627ae09a7ab04f58cb1090d2bAlex Klyubin * 3437a5b72d23c5b24e627ae09a7ab04f58cb1090d2bAlex Klyubin * @param startLen guess about how long the sequence will be 3447a5b72d23c5b24e627ae09a7ab04f58cb1090d2bAlex Klyubin * (used to initialize an auto-growing data structure) 3457a5b72d23c5b24e627ae09a7ab04f58cb1090d2bAlex Klyubin * @return array of the values in the sequence 3467a5b72d23c5b24e627ae09a7ab04f58cb1090d2bAlex Klyubin */ 3477a5b72d23c5b24e627ae09a7ab04f58cb1090d2bAlex Klyubin public DerValue[] getSequence(int startLen) throws IOException { 3487a5b72d23c5b24e627ae09a7ab04f58cb1090d2bAlex Klyubin return getSequence( 3497a5b72d23c5b24e627ae09a7ab04f58cb1090d2bAlex Klyubin startLen, 3507a5b72d23c5b24e627ae09a7ab04f58cb1090d2bAlex Klyubin false); // no need to retain original encoded form 351f5a241465eef5d8b4edaaeccc63680e1ea65bb18Przemyslaw Szczepaniak // END Android-changed: Original encoded form needed for APKs parsing/validation 35251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 35351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 35451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 35551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Return a set of encoded entities. ASN.1 sets are unordered, 35651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * though DER may specify an order for some kinds of sets (such 35751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * as the attributes in an X.500 relative distinguished name) 35851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * to facilitate binary comparisons of encoded values. 35951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 36051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param startLen guess about how large the set will be 36151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * (used to initialize an auto-growing data structure) 36251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return array of the values in the sequence 36351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 36451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public DerValue[] getSet(int startLen) throws IOException { 36551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski tag = (byte)buffer.read(); 36651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (tag != DerValue.tag_Set) 36751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("Set tag error"); 36851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return readVector(startLen); 36951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 37051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 37151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 37251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Return a set of encoded entities. ASN.1 sets are unordered, 37351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * though DER may specify an order for some kinds of sets (such 37451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * as the attributes in an X.500 relative distinguished name) 37551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * to facilitate binary comparisons of encoded values. 37651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 37751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param startLen guess about how large the set will be 37851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * (used to initialize an auto-growing data structure) 37951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param implicit if true tag is assumed implicit. 38051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return array of the values in the sequence 38151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 38251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public DerValue[] getSet(int startLen, boolean implicit) 38351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throws IOException { 384f5a241465eef5d8b4edaaeccc63680e1ea65bb18Przemyslaw Szczepaniak // BEGIN Android-changed: Original encoded form needed for APKs parsing/validation 385ddde3e18b22acdaecb883794f5c8e21f0b87bf2fAlex Klyubin return getSet( 386ddde3e18b22acdaecb883794f5c8e21f0b87bf2fAlex Klyubin startLen, 387ddde3e18b22acdaecb883794f5c8e21f0b87bf2fAlex Klyubin implicit, 388ddde3e18b22acdaecb883794f5c8e21f0b87bf2fAlex Klyubin false); // no need to retain original encoded form 389ddde3e18b22acdaecb883794f5c8e21f0b87bf2fAlex Klyubin } 390ddde3e18b22acdaecb883794f5c8e21f0b87bf2fAlex Klyubin 391ddde3e18b22acdaecb883794f5c8e21f0b87bf2fAlex Klyubin public DerValue[] getSet(int startLen, boolean implicit, 392ddde3e18b22acdaecb883794f5c8e21f0b87bf2fAlex Klyubin boolean originalEncodedFormRetained) 393ddde3e18b22acdaecb883794f5c8e21f0b87bf2fAlex Klyubin throws IOException { 39451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski tag = (byte)buffer.read(); 39551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (!implicit) { 39651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (tag != DerValue.tag_Set) { 39751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("Set tag error"); 39851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 39951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 400ddde3e18b22acdaecb883794f5c8e21f0b87bf2fAlex Klyubin return (readVector(startLen, originalEncodedFormRetained)); 401f5a241465eef5d8b4edaaeccc63680e1ea65bb18Przemyslaw Szczepaniak // END Android-changed: Original encoded form needed for APKs parsing/validation 40251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 40351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 40451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* 40551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Read a "vector" of values ... set or sequence have the 40651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * same encoding, except for the initial tag, so both use 40751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * this same helper routine. 40851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 40951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski protected DerValue[] readVector(int startLen) throws IOException { 410f5a241465eef5d8b4edaaeccc63680e1ea65bb18Przemyslaw Szczepaniak // BEGIN Android-changed: Original encoded form needed for APKs parsing/validation 411ddde3e18b22acdaecb883794f5c8e21f0b87bf2fAlex Klyubin return readVector( 412ddde3e18b22acdaecb883794f5c8e21f0b87bf2fAlex Klyubin startLen, 413ddde3e18b22acdaecb883794f5c8e21f0b87bf2fAlex Klyubin false); // no need to retain original encoded form 414ddde3e18b22acdaecb883794f5c8e21f0b87bf2fAlex Klyubin } 415ddde3e18b22acdaecb883794f5c8e21f0b87bf2fAlex Klyubin 416ddde3e18b22acdaecb883794f5c8e21f0b87bf2fAlex Klyubin /* 417ddde3e18b22acdaecb883794f5c8e21f0b87bf2fAlex Klyubin * Read a "vector" of values ... set or sequence have the 418ddde3e18b22acdaecb883794f5c8e21f0b87bf2fAlex Klyubin * same encoding, except for the initial tag, so both use 419ddde3e18b22acdaecb883794f5c8e21f0b87bf2fAlex Klyubin * this same helper routine. 420ddde3e18b22acdaecb883794f5c8e21f0b87bf2fAlex Klyubin */ 421ddde3e18b22acdaecb883794f5c8e21f0b87bf2fAlex Klyubin protected DerValue[] readVector(int startLen, 422ddde3e18b22acdaecb883794f5c8e21f0b87bf2fAlex Klyubin boolean originalEncodedFormRetained) throws IOException { 423f5a241465eef5d8b4edaaeccc63680e1ea65bb18Przemyslaw Szczepaniak // END Android-changed: Original encoded form needed for APKs parsing/validation 42451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski DerInputStream newstr; 42551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 42651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski byte lenByte = (byte)buffer.read(); 4277b63247eb7ae2638740bd13f370bdcf9d3603407Przemyslaw Szczepaniak int len = getLength(lenByte, buffer); 42851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 42951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (len == -1) { 43051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // indefinite length encoding found 43151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int readLen = buffer.available(); 43251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int offset = 2; // for tag and length bytes 43351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski byte[] indefData = new byte[readLen + offset]; 43451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski indefData[0] = tag; 43551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski indefData[1] = lenByte; 43651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski DataInputStream dis = new DataInputStream(buffer); 43751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski dis.readFully(indefData, offset, readLen); 43851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski dis.close(); 43951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski DerIndefLenConverter derIn = new DerIndefLenConverter(); 44051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski buffer = new DerInputBuffer(derIn.convert(indefData)); 44151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (tag != buffer.read()) 44251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("Indefinite length encoding" + 44351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski " not supported"); 44451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski len = DerInputStream.getLength(buffer); 44551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 44651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 44751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (len == 0) 44851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // return empty array instead of null, which should be 44951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // used only for missing optionals 45051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return new DerValue[0]; 45151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 45251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* 45351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Create a temporary stream from which to read the data, 45451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * unless it's not really needed. 45551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 45651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (buffer.available() == len) 45751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski newstr = this; 45851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski else 45951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski newstr = subStream(len, true); 46051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 46151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* 46251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Pull values out of the stream. 46351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 46451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Vector<DerValue> vec = new Vector<DerValue>(startLen); 46551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski DerValue value; 46651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 46751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski do { 468f5a241465eef5d8b4edaaeccc63680e1ea65bb18Przemyslaw Szczepaniak // Android-changed: Original encoded form needed for APKs parsing/validation 469ddde3e18b22acdaecb883794f5c8e21f0b87bf2fAlex Klyubin value = new DerValue(newstr.buffer, originalEncodedFormRetained); 47051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski vec.addElement(value); 47151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } while (newstr.available() > 0); 47251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 47351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (newstr.available() != 0) 4747b63247eb7ae2638740bd13f370bdcf9d3603407Przemyslaw Szczepaniak throw new IOException("Extra data at end of vector"); 47551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 47651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* 47751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Now stick them into the array we're returning. 47851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 47951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int i, max = vec.size(); 48051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski DerValue[] retval = new DerValue[max]; 48151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 48251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (i = 0; i < max; i++) 48351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski retval[i] = vec.elementAt(i); 48451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 48551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return retval; 48651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 48751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 48851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 48951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Get a single DER-encoded value from the input stream. 49051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * It can often be useful to pull a value from the stream 49151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * and defer parsing it. For example, you can pull a nested 49251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * sequence out with one call, and only examine its elements 49351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * later when you really need to. 49451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 49551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public DerValue getDerValue() throws IOException { 49651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return new DerValue(buffer); 49751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 49851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 49951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 50051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Read a string that was encoded as a UTF8String DER value. 50151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 50251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public String getUTF8String() throws IOException { 50351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return readString(DerValue.tag_UTF8String, "UTF-8", "UTF8"); 50451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 50551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 50651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 50751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Read a string that was encoded as a PrintableString DER value. 50851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 50951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public String getPrintableString() throws IOException { 51051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return readString(DerValue.tag_PrintableString, "Printable", 51151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski "ASCII"); 51251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 51351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 51451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 51551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Read a string that was encoded as a T61String DER value. 51651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 51751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public String getT61String() throws IOException { 51851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* 51951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Works for common characters between T61 and ASCII. 52051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 52151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return readString(DerValue.tag_T61String, "T61", "ISO-8859-1"); 52251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 52351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 52451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 52551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Read a string that was encoded as a IA5tring DER value. 52651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 52751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public String getIA5String() throws IOException { 52851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return readString(DerValue.tag_IA5String, "IA5", "ASCII"); 52951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 53051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 53151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 53251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Read a string that was encoded as a BMPString DER value. 53351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 53451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public String getBMPString() throws IOException { 53551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return readString(DerValue.tag_BMPString, "BMP", 53651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski "UnicodeBigUnmarked"); 53751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 53851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 53951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 54051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Read a string that was encoded as a GeneralString DER value. 54151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 54251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public String getGeneralString() throws IOException { 54351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return readString(DerValue.tag_GeneralString, "General", 54451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski "ASCII"); 54551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 54651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 54751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 54851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Private helper routine to read an encoded string from the input 54951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * stream. 55051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param stringTag the tag for the type of string to read 55151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param stringName a name to display in error messages 55251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param enc the encoder to use to interpret the data. Should 55351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * correspond to the stringTag above. 55451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 55551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private String readString(byte stringTag, String stringName, 55651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String enc) throws IOException { 55751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 55851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (buffer.read() != stringTag) 55951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("DER input not a " + 56051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski stringName + " string"); 56151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 56251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int length = getLength(buffer); 56351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski byte[] retval = new byte[length]; 56451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if ((length != 0) && (buffer.read(retval) != length)) 5657b63247eb7ae2638740bd13f370bdcf9d3603407Przemyslaw Szczepaniak throw new IOException("Short read of DER " + 56651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski stringName + " string"); 56751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 56851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return new String(retval, enc); 56951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 57051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 57151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 57251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Get a UTC encoded time value from the input stream. 57351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 57451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public Date getUTCTime() throws IOException { 57551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (buffer.read() != DerValue.tag_UtcTime) 57651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("DER input, UTCtime tag invalid "); 57751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return buffer.getUTCTime(getLength(buffer)); 57851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 57951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 58051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 58151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Get a Generalized encoded time value from the input stream. 58251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 58351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public Date getGeneralizedTime() throws IOException { 58451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (buffer.read() != DerValue.tag_GeneralizedTime) 58551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("DER input, GeneralizedTime tag invalid "); 58651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return buffer.getGeneralizedTime(getLength(buffer)); 58751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 58851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 58951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* 59051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Get a byte from the input stream. 59151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 59251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // package private 59351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int getByte() throws IOException { 59451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return (0x00ff & buffer.read()); 59551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 59651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 59751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public int peekByte() throws IOException { 59851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return buffer.peek(); 59951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 60051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 60151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // package private 60251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int getLength() throws IOException { 60351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return getLength(buffer); 60451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 60551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 60651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* 60751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Get a length from the input stream, allowing for at most 32 bits of 60851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * encoding to be used. (Not the same as getting a tagged integer!) 60951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 61051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return the length or -1 if indefinite length found. 61151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @exception IOException on parsing error or unsupported lengths. 61251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 61351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski static int getLength(InputStream in) throws IOException { 61451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return getLength(in.read(), in); 61551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 61651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 61751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* 61851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Get a length from the input stream, allowing for at most 32 bits of 61951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * encoding to be used. (Not the same as getting a tagged integer!) 62051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 62151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return the length or -1 if indefinite length found. 62251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @exception IOException on parsing error or unsupported lengths. 62351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 62451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski static int getLength(int lenByte, InputStream in) throws IOException { 62551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int value, tmp; 6267b63247eb7ae2638740bd13f370bdcf9d3603407Przemyslaw Szczepaniak if (lenByte == -1) { 6277b63247eb7ae2638740bd13f370bdcf9d3603407Przemyslaw Szczepaniak throw new IOException("Short read of DER length"); 6287b63247eb7ae2638740bd13f370bdcf9d3603407Przemyslaw Szczepaniak } 62951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 6307b63247eb7ae2638740bd13f370bdcf9d3603407Przemyslaw Szczepaniak String mdName = "DerInputStream.getLength(): "; 63151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski tmp = lenByte; 63251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if ((tmp & 0x080) == 0x00) { // short form, 1 byte datum 63351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski value = tmp; 63451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { // long form or indefinite 63551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski tmp &= 0x07f; 63651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 63751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* 63851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * NOTE: tmp == 0 indicates indefinite length encoded data. 63951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * tmp > 4 indicates more than 4Gb of data. 64051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 64151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (tmp == 0) 64251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return -1; 64351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (tmp < 0 || tmp > 4) 6447b63247eb7ae2638740bd13f370bdcf9d3603407Przemyslaw Szczepaniak throw new IOException(mdName + "lengthTag=" + tmp + ", " 64551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski + ((tmp < 0) ? "incorrect DER encoding." : "too big.")); 64651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 6477b63247eb7ae2638740bd13f370bdcf9d3603407Przemyslaw Szczepaniak value = 0x0ff & in.read(); 6487b63247eb7ae2638740bd13f370bdcf9d3603407Przemyslaw Szczepaniak tmp--; 6497b63247eb7ae2638740bd13f370bdcf9d3603407Przemyslaw Szczepaniak if (value == 0) { 6507b63247eb7ae2638740bd13f370bdcf9d3603407Przemyslaw Szczepaniak // DER requires length value be encoded in minimum number of bytes 6517b63247eb7ae2638740bd13f370bdcf9d3603407Przemyslaw Szczepaniak throw new IOException(mdName + "Redundant length bytes found"); 6527b63247eb7ae2638740bd13f370bdcf9d3603407Przemyslaw Szczepaniak } 6537b63247eb7ae2638740bd13f370bdcf9d3603407Przemyslaw Szczepaniak while (tmp-- > 0) { 65451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski value <<= 8; 65551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski value += 0x0ff & in.read(); 65651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 6574c3078609421ce333468dd415d62980e68d35c9eSergio Giro if (value < 0) { 6587b63247eb7ae2638740bd13f370bdcf9d3603407Przemyslaw Szczepaniak throw new IOException(mdName + "Invalid length bytes"); 6597b63247eb7ae2638740bd13f370bdcf9d3603407Przemyslaw Szczepaniak } else if (value <= 127) { 6607b63247eb7ae2638740bd13f370bdcf9d3603407Przemyslaw Szczepaniak throw new IOException(mdName + "Should use short form for length"); 6614c3078609421ce333468dd415d62980e68d35c9eSergio Giro } 66251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 66351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return value; 66451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 66551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 66651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 66751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Mark the current position in the buffer, so that 66851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * a later call to <code>reset</code> will return here. 66951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 67051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void mark(int value) { buffer.mark(value); } 67151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 67251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 67351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 67451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Return to the position of the last <code>mark</code> 67551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * call. A mark is implicitly set at the beginning of 67651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the stream when it is created. 67751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 67851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void reset() { buffer.reset(); } 67951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 68051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 68151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 68251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Returns the number of bytes available for reading. 68351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This is most useful for testing whether the stream is 68451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * empty. 68551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 68651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public int available() { return buffer.available(); } 68751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski} 688