/*
 * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package sun.security.util;

import java.io.InputStream;
import java.io.IOException;
import java.io.EOFException;
import java.util.Date;
import java.util.Vector;
import java.math.BigInteger;
import java.io.DataInputStream;

/**
 * A DER input stream, used for parsing ASN.1 DER-encoded data such as
 * that found in X.509 certificates.  DER is a subset of BER/1, which has
 * the advantage that it allows only a single encoding of primitive data.
 * (High level data such as dates still support many encodings.)  That is,
 * it uses the "Definite" Encoding Rules (DER) not the "Basic" ones (BER).
 *
 * <P>Note that, like BER/1, DER streams are streams of explicitly
 * tagged data values.  Accordingly, this programming interface does
 * not expose any variant of the java.io.InputStream interface, since
 * that kind of input stream holds untagged data values and using that
 * I/O model could prevent correct parsing of the DER data.
 *
 * <P>At this time, this class supports only a subset of the types of DER
 * data encodings which are defined.  That subset is sufficient for parsing
 * most X.509 certificates.
 *
 *
 * @author David Brownell
 * @author Amit Kapoor
 * @author Hemma Prafullchandra
 */

public class DerInputStream {

    /*
     * This version only supports fully buffered DER.  This is easy to
     * work with, though if large objects are manipulated DER becomes
     * awkward to deal with.  That's where BER is useful, since BER
     * handles streaming data relatively well.
     */
    DerInputBuffer      buffer;

    /** The DER tag of the value; one of the tag_ constants. */
    public byte         tag;

    /**
     * Create a DER input stream from a data buffer.  The buffer is not
     * copied, it is shared.  Accordingly, the buffer should be treated
     * as read-only.
     *
     * @param data the buffer from which to create the string (CONSUMED)
     */
    public DerInputStream(byte[] data) throws IOException {
        init(data, 0, data.length, true);
    }

    /**
     * Create a DER input stream from part of a data buffer.
     * The buffer is not copied, it is shared.  Accordingly, the
     * buffer should be treated as read-only.
     *
     * @param data the buffer from which to create the string (CONSUMED)
     * @param offset the first index of <em>data</em> which will
     *          be read as DER input in the new stream
     * @param len how long a chunk of the buffer to use,
     *          starting at "offset"
     */
    public DerInputStream(byte[] data, int offset, int len) throws IOException {
        init(data, offset, len, true);
    }

    /**
     * Create a DER input stream from part of a data buffer with
     * additional arg to indicate whether to allow constructed
     * indefinite-length encoding.
     * The buffer is not copied, it is shared.  Accordingly, the
     * buffer should be treated as read-only.
     *
     * @param data the buffer from which to create the string (CONSUMED)
     * @param offset the first index of <em>data</em> which will
     *          be read as DER input in the new stream
     * @param len how long a chunk of the buffer to use,
     *          starting at "offset"
     * @param allowIndefiniteLength whether to allow constructed
     *          indefinite-length encoding
     */
    public DerInputStream(byte[] data, int offset, int len,
        boolean allowIndefiniteLength) throws IOException {
        init(data, offset, len, allowIndefiniteLength);
    }

    /*
     * private helper routine
     */
    private void init(byte[] data, int offset, int len,
        boolean allowIndefiniteLength) throws IOException {
        if ((offset+2 > data.length) || (offset+len > data.length)) {
            throw new IOException("Encoding bytes too short");
        }
        // check for indefinite length encoding
        if (DerIndefLenConverter.isIndefinite(data[offset+1])) {
            if (!allowIndefiniteLength) {
                throw new IOException("Indefinite length BER encoding found");
            } else {
                byte[] inData = new byte[len];
                System.arraycopy(data, offset, inData, 0, len);

                DerIndefLenConverter derIn = new DerIndefLenConverter();
                buffer = new DerInputBuffer(derIn.convert(inData));
            }
        } else
            buffer = new DerInputBuffer(data, offset, len);
        buffer.mark(Integer.MAX_VALUE);
    }

    DerInputStream(DerInputBuffer buf) {
        buffer = buf;
        buffer.mark(Integer.MAX_VALUE);
    }

    /**
     * Creates a new DER input stream from part of this input stream.
     *
     * @param len how long a chunk of the current input stream to use,
     *          starting at the current position.
     * @param do_skip true if the existing data in the input stream should
     *          be skipped.  If this value is false, the next data read
     *          on this stream and the newly created stream will be the
     *          same.
     */
    public DerInputStream subStream(int len, boolean do_skip)
    throws IOException {
        DerInputBuffer  newbuf = buffer.dup();

        newbuf.truncate(len);
        if (do_skip) {
            buffer.skip(len);
        }
        return new DerInputStream(newbuf);
    }

    /**
     * Return what has been written to this DerInputStream
     * as a byte array. Useful for debugging.
     */
    public byte[] toByteArray() {
        return buffer.toByteArray();
    }

    /*
     * PRIMITIVES -- these are "universal" ASN.1 simple types.
     *
     *  INTEGER, ENUMERATED, BIT STRING, OCTET STRING, NULL
     *  OBJECT IDENTIFIER, SEQUENCE (OF), SET (OF)
     *  UTF8String, PrintableString, T61String, IA5String, UTCTime,
     *  GeneralizedTime, BMPString.
     * Note: UniversalString not supported till encoder is available.
     */

    /**
     * Get an integer from the input stream as an integer.
     *
     * @return the integer held in this DER input stream.
     */
    public int getInteger() throws IOException {
        if (buffer.read() != DerValue.tag_Integer) {
            throw new IOException("DER input, Integer tag error");
        }
        return buffer.getInteger(getLength(buffer));
    }

    /**
     * Get a integer from the input stream as a BigInteger object.
     *
     * @return the integer held in this DER input stream.
     */
    public BigInteger getBigInteger() throws IOException {
        if (buffer.read() != DerValue.tag_Integer) {
            throw new IOException("DER input, Integer tag error");
        }
        return buffer.getBigInteger(getLength(buffer), false);
    }

    /**
     * Returns an ASN.1 INTEGER value as a positive BigInteger.
     * This is just to deal with implementations that incorrectly encode
     * some values as negative.
     *
     * @return the integer held in this DER value as a BigInteger.
     */
    public BigInteger getPositiveBigInteger() throws IOException {
        if (buffer.read() != DerValue.tag_Integer) {
            throw new IOException("DER input, Integer tag error");
        }
        return buffer.getBigInteger(getLength(buffer), true);
    }

    /**
     * Get an enumerated from the input stream.
     *
     * @return the integer held in this DER input stream.
     */
    public int getEnumerated() throws IOException {
        if (buffer.read() != DerValue.tag_Enumerated) {
            throw new IOException("DER input, Enumerated tag error");
        }
        return buffer.getInteger(getLength(buffer));
    }

    /**
     * Get a bit string from the input stream. Padded bits (if any)
     * will be stripped off before the bit string is returned.
     */
    public byte[] getBitString() throws IOException {
        if (buffer.read() != DerValue.tag_BitString)
            throw new IOException("DER input not an bit string");

        return buffer.getBitString(getLength(buffer));
    }

    /**
     * Get a bit string from the input stream.  The bit string need
     * not be byte-aligned.
     */
    public BitArray getUnalignedBitString() throws IOException {
        if (buffer.read() != DerValue.tag_BitString)
            throw new IOException("DER input not a bit string");

        int length = getLength(buffer) - 1;

        /*
         * First byte = number of excess bits in the last octet of the
         * representation.
         */
        int excessBits = buffer.read();
        if (excessBits < 0) {
            throw new IOException("Unused bits of bit string invalid");
        }
        int validBits = length*8 - excessBits;
        if (validBits < 0) {
            throw new IOException("Valid bits of bit string invalid");
        }

        byte[] repn = new byte[length];

        if ((length != 0) && (buffer.read(repn) != length)) {
            throw new IOException("Short read of DER bit string");
        }

        return new BitArray(validBits, repn);
    }

    /**
     * Returns an ASN.1 OCTET STRING from the input stream.
     */
    public byte[] getOctetString() throws IOException {
        if (buffer.read() != DerValue.tag_OctetString)
            throw new IOException("DER input not an octet string");

        int length = getLength(buffer);
        byte[] retval = new byte[length];
        if ((length != 0) && (buffer.read(retval) != length))
            throw new IOException("Short read of DER octet string");

        return retval;
    }

    /**
     * Returns the asked number of bytes from the input stream.
     */
    public void getBytes(byte[] val) throws IOException {
        if ((val.length != 0) && (buffer.read(val) != val.length)) {
            throw new IOException("Short read of DER octet string");
        }
    }

    /**
     * Reads an encoded null value from the input stream.
     */
    public void getNull() throws IOException {
        if (buffer.read() != DerValue.tag_Null || buffer.read() != 0)
            throw new IOException("getNull, bad data");
    }

    /**
     * Reads an X.200 style Object Identifier from the stream.
     */
    public ObjectIdentifier getOID() throws IOException {
        return new ObjectIdentifier(this);
    }

    /**
     * Return a sequence of encoded entities.  ASN.1 sequences are
     * ordered, and they are often used, like a "struct" in C or C++,
     * to group data values.  They may have optional or context
     * specific values.
     *
     * @param startLen guess about how long the sequence will be
     *          (used to initialize an auto-growing data structure)
     * @return array of the values in the sequence
     */
    public DerValue[] getSequence(int startLen,
            boolean originalEncodedFormRetained) throws IOException {
        tag = (byte)buffer.read();
        if (tag != DerValue.tag_Sequence)
            throw new IOException("Sequence tag error");
        return readVector(startLen, originalEncodedFormRetained);
    }

    /**
     * Return a sequence of encoded entities.  ASN.1 sequences are
     * ordered, and they are often used, like a "struct" in C or C++,
     * to group data values.  They may have optional or context
     * specific values.
     *
     * @param startLen guess about how long the sequence will be
     *          (used to initialize an auto-growing data structure)
     * @return array of the values in the sequence
     */
    public DerValue[] getSequence(int startLen) throws IOException {
        return getSequence(
                startLen,
                false); // no need to retain original encoded form
    }

    /**
     * Return a set of encoded entities.  ASN.1 sets are unordered,
     * though DER may specify an order for some kinds of sets (such
     * as the attributes in an X.500 relative distinguished name)
     * to facilitate binary comparisons of encoded values.
     *
     * @param startLen guess about how large the set will be
     *          (used to initialize an auto-growing data structure)
     * @return array of the values in the sequence
     */
    public DerValue[] getSet(int startLen) throws IOException {
        tag = (byte)buffer.read();
        if (tag != DerValue.tag_Set)
            throw new IOException("Set tag error");
        return readVector(startLen);
    }

    /**
     * Return a set of encoded entities.  ASN.1 sets are unordered,
     * though DER may specify an order for some kinds of sets (such
     * as the attributes in an X.500 relative distinguished name)
     * to facilitate binary comparisons of encoded values.
     *
     * @param startLen guess about how large the set will be
     *          (used to initialize an auto-growing data structure)
     * @param implicit if true tag is assumed implicit.
     * @return array of the values in the sequence
     */
    public DerValue[] getSet(int startLen, boolean implicit)
        throws IOException {
        return getSet(
            startLen,
            implicit,
            false); // no need to retain original encoded form
    }

    public DerValue[] getSet(int startLen, boolean implicit,
            boolean originalEncodedFormRetained)
        throws IOException {
        tag = (byte)buffer.read();
        if (!implicit) {
            if (tag != DerValue.tag_Set) {
                throw new IOException("Set tag error");
            }
        }
        return (readVector(startLen, originalEncodedFormRetained));
    }

    /*
     * Read a "vector" of values ... set or sequence have the
     * same encoding, except for the initial tag, so both use
     * this same helper routine.
     */
    protected DerValue[] readVector(int startLen) throws IOException {
        return readVector(
            startLen,
            false); // no need to retain original encoded form
    }

    /*
     * Read a "vector" of values ... set or sequence have the
     * same encoding, except for the initial tag, so both use
     * this same helper routine.
     */
    protected DerValue[] readVector(int startLen,
            boolean originalEncodedFormRetained) throws IOException {
        DerInputStream  newstr;

        byte lenByte = (byte)buffer.read();
        int len = getLength(lenByte, buffer);

        if (len == -1) {
           // indefinite length encoding found
           int readLen = buffer.available();
           int offset = 2;     // for tag and length bytes
           byte[] indefData = new byte[readLen + offset];
           indefData[0] = tag;
           indefData[1] = lenByte;
           DataInputStream dis = new DataInputStream(buffer);
           dis.readFully(indefData, offset, readLen);
           dis.close();
           DerIndefLenConverter derIn = new DerIndefLenConverter();
           buffer = new DerInputBuffer(derIn.convert(indefData));
           if (tag != buffer.read())
                throw new IOException("Indefinite length encoding" +
                        " not supported");
           len = DerInputStream.getLength(buffer);
        }

        if (len == 0)
            // return empty array instead of null, which should be
            // used only for missing optionals
            return new DerValue[0];

        /*
         * Create a temporary stream from which to read the data,
         * unless it's not really needed.
         */
        if (buffer.available() == len)
            newstr = this;
        else
            newstr = subStream(len, true);

        /*
         * Pull values out of the stream.
         */
        Vector<DerValue> vec = new Vector<DerValue>(startLen);
        DerValue value;

        do {
            value = new DerValue(newstr.buffer, originalEncodedFormRetained);
            vec.addElement(value);
        } while (newstr.available() > 0);

        if (newstr.available() != 0)
            throw new IOException("Extra data at end of vector");

        /*
         * Now stick them into the array we're returning.
         */
        int             i, max = vec.size();
        DerValue[]      retval = new DerValue[max];

        for (i = 0; i < max; i++)
            retval[i] = vec.elementAt(i);

        return retval;
    }

    /**
     * Get a single DER-encoded value from the input stream.
     * It can often be useful to pull a value from the stream
     * and defer parsing it.  For example, you can pull a nested
     * sequence out with one call, and only examine its elements
     * later when you really need to.
     */
    public DerValue getDerValue() throws IOException {
        return new DerValue(buffer);
    }

    /**
     * Read a string that was encoded as a UTF8String DER value.
     */
    public String getUTF8String() throws IOException {
        return readString(DerValue.tag_UTF8String, "UTF-8", "UTF8");
    }

    /**
     * Read a string that was encoded as a PrintableString DER value.
     */
    public String getPrintableString() throws IOException {
        return readString(DerValue.tag_PrintableString, "Printable",
                          "ASCII");
    }

    /**
     * Read a string that was encoded as a T61String DER value.
     */
    public String getT61String() throws IOException {
        /*
         * Works for common characters between T61 and ASCII.
         */
        return readString(DerValue.tag_T61String, "T61", "ISO-8859-1");
    }

    /**
     * Read a string that was encoded as a IA5tring DER value.
     */
    public String getIA5String() throws IOException {
        return readString(DerValue.tag_IA5String, "IA5", "ASCII");
    }

    /**
     * Read a string that was encoded as a BMPString DER value.
     */
    public String getBMPString() throws IOException {
        return readString(DerValue.tag_BMPString, "BMP",
                          "UnicodeBigUnmarked");
    }

    /**
     * Read a string that was encoded as a GeneralString DER value.
     */
    public String getGeneralString() throws IOException {
        return readString(DerValue.tag_GeneralString, "General",
                          "ASCII");
    }

    /**
     * Private helper routine to read an encoded string from the input
     * stream.
     * @param stringTag the tag for the type of string to read
     * @param stringName a name to display in error messages
     * @param enc the encoder to use to interpret the data. Should
     * correspond to the stringTag above.
     */
    private String readString(byte stringTag, String stringName,
                              String enc) throws IOException {

        if (buffer.read() != stringTag)
            throw new IOException("DER input not a " +
                                  stringName + " string");

        int length = getLength(buffer);
        byte[] retval = new byte[length];
        if ((length != 0) && (buffer.read(retval) != length))
            throw new IOException("Short read of DER " +
                                  stringName + " string");

        return new String(retval, enc);
    }

    /**
     * Get a UTC encoded time value from the input stream.
     */
    public Date getUTCTime() throws IOException {
        if (buffer.read() != DerValue.tag_UtcTime)
            throw new IOException("DER input, UTCtime tag invalid ");
        return buffer.getUTCTime(getLength(buffer));
    }

    /**
     * Get a Generalized encoded time value from the input stream.
     */
    public Date getGeneralizedTime() throws IOException {
        if (buffer.read() != DerValue.tag_GeneralizedTime)
            throw new IOException("DER input, GeneralizedTime tag invalid ");
        return buffer.getGeneralizedTime(getLength(buffer));
    }

    /*
     * Get a byte from the input stream.
     */
    // package private
    int getByte() throws IOException {
        return (0x00ff & buffer.read());
    }

    public int peekByte() throws IOException {
        return buffer.peek();
    }

    // package private
    int getLength() throws IOException {
        return getLength(buffer);
    }

    /*
     * Get a length from the input stream, allowing for at most 32 bits of
     * encoding to be used.  (Not the same as getting a tagged integer!)
     *
     * @return the length or -1 if indefinite length found.
     * @exception IOException on parsing error or unsupported lengths.
     */
    static int getLength(InputStream in) throws IOException {
        return getLength(in.read(), in);
    }

    /*
     * Get a length from the input stream, allowing for at most 32 bits of
     * encoding to be used.  (Not the same as getting a tagged integer!)
     *
     * @return the length or -1 if indefinite length found.
     * @exception IOException on parsing error or unsupported lengths.
     */
    static int getLength(int lenByte, InputStream in) throws IOException {
        int value, tmp;
        if (lenByte == -1) {
            throw new IOException("Short read of DER length");
        }

        String mdName = "DerInputStream.getLength(): ";
        tmp = lenByte;
        if ((tmp & 0x080) == 0x00) { // short form, 1 byte datum
            value = tmp;
        } else {                     // long form or indefinite
            tmp &= 0x07f;

            /*
             * NOTE:  tmp == 0 indicates indefinite length encoded data.
             * tmp > 4 indicates more than 4Gb of data.
             */
            if (tmp == 0)
                return -1;
            if (tmp < 0 || tmp > 4)
                throw new IOException(mdName + "lengthTag=" + tmp + ", "
                    + ((tmp < 0) ? "incorrect DER encoding." : "too big."));

            value = 0x0ff & in.read();
            tmp--;
            if (value == 0) {
                // DER requires length value be encoded in minimum number of bytes
                throw new IOException(mdName + "Redundant length bytes found");
            }
            while (tmp-- > 0) {
                value <<= 8;
                value += 0x0ff & in.read();
            }
            if (value < 0) {
                throw new IOException(mdName + "Invalid length bytes");
            } else if (value <= 127) {
                throw new IOException(mdName + "Should use short form for length");
            }
        }
        return value;
    }

    /**
     * Mark the current position in the buffer, so that
     * a later call to <code>reset</code> will return here.
     */
    public void mark(int value) { buffer.mark(value); }


    /**
     * Return to the position of the last <code>mark</code>
     * call.  A mark is implicitly set at the beginning of
     * the stream when it is created.
     */
    public void reset() { buffer.reset(); }


    /**
     * Returns the number of bytes available for reading.
     * This is most useful for testing whether the stream is
     * empty.
     */
    public int available() { return buffer.available(); }
}
