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