/*
 * Copyright (c) 1996, 2006, 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.*;
import java.math.BigInteger;
import java.util.Arrays;

/**
 * Represent an ISO Object Identifier.
 *
 * <P>Object Identifiers are arbitrary length hierarchical identifiers.
 * The individual components are numbers, and they define paths from the
 * root of an ISO-managed identifier space.  You will sometimes see a
 * string name used instead of (or in addition to) the numerical id.
 * These are synonyms for the numerical IDs, but are not widely used
 * since most sites do not know all the requisite strings, while all
 * sites can parse the numeric forms.
 *
 * <P>So for example, JavaSoft has the sole authority to assign the
 * meaning to identifiers below the 1.3.6.1.4.1.42.2.17 node in the
 * hierarchy, and other organizations can easily acquire the ability
 * to assign such unique identifiers.
 *
 * @author David Brownell
 * @author Amit Kapoor
 * @author Hemma Prafullchandra
 */

final public
class ObjectIdentifier implements Serializable
{
    /**
     * We use the DER value (no tag, no length) as the internal format
     * @serial
     */
    private byte[] encoding = null;

    private transient volatile String stringForm;

    /*
     * IMPORTANT NOTES FOR CODE CHANGES (bug 4811968) IN JDK 1.7.0
     * ===========================================================
     *
     * (Almost) serialization compatibility with old versions:
     *
     * serialVersionUID is unchanged. Old field "component" is changed to
     * type Object so that "poison" (unknown object type for old versions)
     * can be put inside if there are huge components that cannot be saved
     * as integers.
     *
     * New version use the new filed "encoding" only.
     *
     * Below are all 4 cases in a serialization/deserialization process:
     *
     * 1. old -> old: Not covered here
     * 2. old -> new: There's no "encoding" field, new readObject() reads
     *    "components" and "componentLen" instead and inits correctly.
     * 3. new -> new: "encoding" field exists, new readObject() uses it
     *    (ignoring the other 2 fields) and inits correctly.
     * 4. new -> old: old readObject() only recognizes "components" and
     *    "componentLen" fields. If no huge components are involved, they
     *    are serialized as legal values and old object can init correctly.
     *    Otherwise, old object cannot recognize the form (component not int[])
     *    and throw a ClassNotFoundException at deserialization time.
     *
     * Therfore, for the first 3 cases, exact compatibility is preserved. In
     * the 4th case, non-huge OID is still supportable in old versions, while
     * huge OID is not.
     */
    private static final long serialVersionUID = 8697030238860181294L;

    /**
     * Changed to Object
     * @serial
     */
    private Object      components   = null;          // path from root
    /**
     * @serial
     */
    private int         componentLen = -1;            // how much is used.

    // Is the components field calculated?
    transient private boolean   componentsCalculated = false;

    private void readObject(ObjectInputStream is)
            throws IOException, ClassNotFoundException {
        is.defaultReadObject();

        if (encoding == null) {  // from an old version
            init((int[])components, componentLen);
        }
    }

    private void writeObject(ObjectOutputStream os)
            throws IOException {
        if (!componentsCalculated) {
            int[] comps = toIntArray();
            if (comps != null) {    // every one understands this
                components = comps;
                componentLen = comps.length;
            } else {
                components = HugeOidNotSupportedByOldJDK.theOne;
            }
            componentsCalculated = true;
        }
        os.defaultWriteObject();
    }

    static class HugeOidNotSupportedByOldJDK implements Serializable {
        private static final long serialVersionUID = 1L;
        static HugeOidNotSupportedByOldJDK theOne = new HugeOidNotSupportedByOldJDK();
    }

    /**
     * Constructs, from a string.  This string should be of the form 1.23.56.
     * Validity check included.
     */
    public ObjectIdentifier (String oid) throws IOException
    {
        int ch = '.';
        int start = 0;
        int end = 0;

        int pos = 0;
        byte[] tmp = new byte[oid.length()];
        int first = 0, second;
        int count = 0;

        try {
            String comp = null;
            do {
                int length = 0; // length of one section
                end = oid.indexOf(ch,start);
                if (end == -1) {
                    comp = oid.substring(start);
                    length = oid.length() - start;
                } else {
                    comp = oid.substring(start,end);
                    length = end - start;
                }

                if (length > 9) {
                    BigInteger bignum = new BigInteger(comp);
                    if (count == 0) {
                        checkFirstComponent(bignum);
                        first = bignum.intValue();
                    } else {
                        if (count == 1) {
                            checkSecondComponent(first, bignum);
                            bignum = bignum.add(BigInteger.valueOf(40*first));
                        } else {
                            checkOtherComponent(count, bignum);
                        }
                        pos += pack7Oid(bignum, tmp, pos);
                    }
                } else {
                    int num = Integer.parseInt(comp);
                    if (count == 0) {
                        checkFirstComponent(num);
                        first = num;
                    } else {
                        if (count == 1) {
                            checkSecondComponent(first, num);
                            num += 40 * first;
                        } else {
                            checkOtherComponent(count, num);
                        }
                        pos += pack7Oid(num, tmp, pos);
                    }
                }
                start = end + 1;
                count++;
            } while (end != -1);

            checkCount(count);
            encoding = new byte[pos];
            System.arraycopy(tmp, 0, encoding, 0, pos);
            this.stringForm = oid;
        } catch (IOException ioe) { // already detected by checkXXX
            throw ioe;
        } catch (Exception e) {
            throw new IOException("ObjectIdentifier() -- Invalid format: "
                    + e.toString(), e);
        }
    }

    /**
     * Constructor, from an array of integers.
     * Validity check included.
     */
    public ObjectIdentifier (int values []) throws IOException
    {
        checkCount(values.length);
        checkFirstComponent(values[0]);
        checkSecondComponent(values[0], values[1]);
        for (int i=2; i<values.length; i++)
            checkOtherComponent(i, values[i]);
        init(values, values.length);
    }

    /**
     * Constructor, from an ASN.1 encoded input stream.
     * Validity check NOT included.
     * The encoding of the ID in the stream uses "DER", a BER/1 subset.
     * In this case, that means a triple { typeId, length, data }.
     *
     * <P><STRONG>NOTE:</STRONG>  When an exception is thrown, the
     * input stream has not been returned to its "initial" state.
     *
     * @param in DER-encoded data holding an object ID
     * @exception IOException indicates a decoding error
     */
    public ObjectIdentifier (DerInputStream in) throws IOException
    {
        byte    type_id;
        int     bufferEnd;

        /*
         * Object IDs are a "universal" type, and their tag needs only
         * one byte of encoding.  Verify that the tag of this datum
         * is that of an object ID.
         *
         * Then get and check the length of the ID's encoding.  We set
         * up so that we can use in.available() to check for the end of
         * this value in the data stream.
         */
        type_id = (byte) in.getByte ();
        if (type_id != DerValue.tag_ObjectId)
            throw new IOException (
                "ObjectIdentifier() -- data isn't an object ID"
                + " (tag = " +  type_id + ")"
                );

        encoding = new byte[in.getLength()];
        in.getBytes(encoding);
        check(encoding);
    }

    /*
     * Constructor, from the rest of a DER input buffer;
     * the tag and length have been removed/verified
     * Validity check NOT included.
     */
    ObjectIdentifier (DerInputBuffer buf) throws IOException
    {
        DerInputStream in = new DerInputStream(buf);
        encoding = new byte[in.available()];
        in.getBytes(encoding);
        check(encoding);
    }

    private void init(int[] components, int length) {
        int pos = 0;
        byte[] tmp = new byte[length*5+1];  // +1 for empty input

        if (components[1] < Integer.MAX_VALUE - components[0]*40)
            pos += pack7Oid(components[0]*40+components[1], tmp, pos);
        else {
            BigInteger big = BigInteger.valueOf(components[1]);
            big = big.add(BigInteger.valueOf(components[0]*40));
            pos += pack7Oid(big, tmp, pos);
        }

        for (int i=2; i<length; i++) {
            pos += pack7Oid(components[i], tmp, pos);
        }
        encoding = new byte[pos];
        System.arraycopy(tmp, 0, encoding, 0, pos);
    }

    /**
     * This method is kept for compatibility reasons. The new implementation
     * does the check and conversion. All around the JDK, the method is called
     * in static blocks to initialize pre-defined ObjectIdentifieies. No
     * obvious performance hurt will be made after this change.
     *
     * Old doc: Create a new ObjectIdentifier for internal use. The values are
     * neither checked nor cloned.
     */
    public static ObjectIdentifier newInternal(int[] values) {
        try {
            return new ObjectIdentifier(values);
        } catch (IOException ex) {
            throw new RuntimeException(ex);
            // Should not happen, internal calls always uses legal values.
        }
    }

    /*
     * n.b. the only public interface is DerOutputStream.putOID()
     */
    void encode (DerOutputStream out) throws IOException
    {
        out.write (DerValue.tag_ObjectId, encoding);
    }

    /**
     * @deprecated Use equals((Object)oid)
     */
    @Deprecated
    public boolean equals(ObjectIdentifier other) {
        return equals((Object)other);
    }

    /**
     * Compares this identifier with another, for equality.
     *
     * @return true iff the names are identical.
     */
    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj instanceof ObjectIdentifier == false) {
            return false;
        }
        ObjectIdentifier other = (ObjectIdentifier)obj;
        return Arrays.equals(encoding, other.encoding);
    }

    @Override
    public int hashCode() {
        return Arrays.hashCode(encoding);
    }

    /**
     * Private helper method for serialization. To be compatible with old
     * versions of JDK.
     * @return components in an int array, if all the components are less than
     *         Integer.MAX_VALUE. Otherwise, null.
     */
    private int[] toIntArray() {
        int length = encoding.length;
        int[] result = new int[20];
        int which = 0;
        int fromPos = 0;
        for (int i = 0; i < length; i++) {
            if ((encoding[i] & 0x80) == 0) {
                // one section [fromPos..i]
                if (i - fromPos + 1 > 4) {
                    BigInteger big = new BigInteger(pack(encoding, fromPos, i-fromPos+1, 7, 8));
                    if (fromPos == 0) {
                        result[which++] = 2;
                        BigInteger second = big.subtract(BigInteger.valueOf(80));
                        if (second.compareTo(BigInteger.valueOf(Integer.MAX_VALUE)) == 1) {
                            return null;
                        } else {
                            result[which++] = second.intValue();
                        }
                    } else {
                        if (big.compareTo(BigInteger.valueOf(Integer.MAX_VALUE)) == 1) {
                            return null;
                        } else {
                            result[which++] = big.intValue();
                        }
                    }
                } else {
                    int retval = 0;
                    for (int j = fromPos; j <= i; j++) {
                        retval <<= 7;
                        byte tmp = encoding[j];
                        retval |= (tmp & 0x07f);
                    }
                    if (fromPos == 0) {
                        if (retval < 80) {
                            result[which++] = retval / 40;
                            result[which++] = retval % 40;
                        } else {
                            result[which++] = 2;
                            result[which++] = retval - 80;
                        }
                    } else {
                        result[which++] = retval;
                    }
                }
                fromPos = i+1;
            }
            if (which >= result.length) {
                result = Arrays.copyOf(result, which + 10);
            }
        }
        return Arrays.copyOf(result, which);
    }

    /**
     * Returns a string form of the object ID.  The format is the
     * conventional "dot" notation for such IDs, without any
     * user-friendly descriptive strings, since those strings
     * will not be understood everywhere.
     */
    @Override
    public String toString() {
        String s = stringForm;
        if (s == null) {
            int length = encoding.length;
            StringBuffer sb = new StringBuffer(length * 4);

            int fromPos = 0;
            for (int i = 0; i < length; i++) {
                if ((encoding[i] & 0x80) == 0) {
                    // one section [fromPos..i]
                    if (fromPos != 0) {  // not the first segment
                        sb.append('.');
                    }
                    if (i - fromPos + 1 > 4) { // maybe big integer
                        BigInteger big = new BigInteger(pack(encoding, fromPos, i-fromPos+1, 7, 8));
                        if (fromPos == 0) {
                            // first section encoded with more than 4 bytes,
                            // must be 2.something
                            sb.append("2.");
                            sb.append(big.subtract(BigInteger.valueOf(80)));
                        } else {
                            sb.append(big);
                        }
                    } else { // small integer
                        int retval = 0;
                        for (int j = fromPos; j <= i; j++) {
                            retval <<= 7;
                            byte tmp = encoding[j];
                            retval |= (tmp & 0x07f);
                        }
                        if (fromPos == 0) {
                            if (retval < 80) {
                                sb.append(retval/40);
                                sb.append('.');
                                sb.append(retval%40);
                            } else {
                                sb.append("2.");
                                sb.append(retval - 80);
                            }
                        } else {
                            sb.append(retval);
                        }
                    }
                    fromPos = i+1;
                }
            }
            s = sb.toString();
            stringForm = s;
        }
        return s;
    }

    /**
     * Repack all bits from input to output. On the both sides, only a portion
     * (from the least significant bit) of the 8 bits in a byte is used. This
     * number is defined as the number of useful bits (NUB) for the array. All the
     * used bits from the input byte array and repacked into the output in the
     * exactly same order. The output bits are aligned so that the final bit of
     * the input (the least significant bit in the last byte), when repacked as
     * the final bit of the output, is still at the least significant position.
     * Zeroes will be padded on the left side of the first output byte if
     * necessary. All unused bits in the output are also zeroed.
     *
     * For example: if the input is 01001100 with NUB 8, the output which
     * has a NUB 6 will look like:
     *      00000001 00001100
     * The first 2 bits of the output bytes are unused bits. The other bits
     * turn out to be 000001 001100. While the 8 bits on the right are from
     * the input, the left 4 zeroes are padded to fill the 6 bits space.
     *
     * @param in        the input byte array
     * @param ioffset   start point inside <code>in</code>
     * @param ilength   number of bytes to repack
     * @param iw        NUB for input
     * @param ow        NUB for output
     * @return          the repacked bytes
     */
    private static byte[] pack(byte[] in, int ioffset, int ilength, int iw, int ow) {
        assert (iw > 0 && iw <= 8): "input NUB must be between 1 and 8";
        assert (ow > 0 && ow <= 8): "output NUB must be between 1 and 8";

        if (iw == ow) {
            return in.clone();
        }

        int bits = ilength * iw;    // number of all used bits
        byte[] out = new byte[(bits+ow-1)/ow];

        // starting from the 0th bit in the input
        int ipos = 0;

        // the number of padding 0's needed in the output, skip them
        int opos = (bits+ow-1)/ow*ow-bits;

        while(ipos < bits) {
            int count = iw - ipos%iw;   // unpacked bits in current input byte
            if (count > ow - opos%ow) { // free space available in output byte
                count = ow - opos%ow;   // choose the smaller number
            }
            // and move them!
            out[opos/ow] |=                         // paste!
                (((in[ioffset+ipos/iw]+256)         // locate the byte (+256 so that it's never negative)
                    >> (iw-ipos%iw-count))          // move to the end of a byte
                        & ((1 << (count))-1))       // zero out all other bits
                            << (ow-opos%ow-count);  // move to the output position
            ipos += count;  // advance
            opos += count;  // advance
        }
        return out;
    }

    /**
     * Repack from NUB 8 to a NUB 7 OID sub-identifier, remove all
     * unnecessary 0 headings, set the first bit of all non-tail
     * output bytes to 1 (as ITU-T Rec. X.690 8.19.2 says), and
     * paste it into an existing byte array.
     * @param out the existing array to be pasted into
     * @param ooffset the starting position to paste
     * @return the number of bytes pasted
     */
    private static int pack7Oid(byte[] in, int ioffset, int ilength, byte[] out, int ooffset) {
        byte[] pack = pack(in, ioffset, ilength, 8, 7);
        int firstNonZero = pack.length-1;   // paste at least one byte
        for (int i=pack.length-2; i>=0; i--) {
            if (pack[i] != 0) {
                firstNonZero = i;
            }
            pack[i] |= 0x80;
        }
        System.arraycopy(pack, firstNonZero, out, ooffset, pack.length-firstNonZero);
        return pack.length-firstNonZero;
    }

    /**
     * Repack from NUB 7 to NUB 8, remove all unnecessary 0
     * headings, and paste it into an existing byte array.
     * @param out the existing array to be pasted into
     * @param ooffset the starting position to paste
     * @return the number of bytes pasted
     */
    private static int pack8(byte[] in, int ioffset, int ilength, byte[] out, int ooffset) {
        byte[] pack = pack(in, ioffset, ilength, 7, 8);
        int firstNonZero = pack.length-1;   // paste at least one byte
        for (int i=pack.length-2; i>=0; i--) {
            if (pack[i] != 0) {
                firstNonZero = i;
            }
        }
        System.arraycopy(pack, firstNonZero, out, ooffset, pack.length-firstNonZero);
        return pack.length-firstNonZero;
    }

    /**
     * Pack the int into a OID sub-identifier DER encoding
     */
    private static int pack7Oid(int input, byte[] out, int ooffset) {
        byte[] b = new byte[4];
        b[0] = (byte)(input >> 24);
        b[1] = (byte)(input >> 16);
        b[2] = (byte)(input >> 8);
        b[3] = (byte)(input);
        return pack7Oid(b, 0, 4, out, ooffset);
    }

    /**
     * Pack the BigInteger into a OID subidentifier DER encoding
     */
    private static int pack7Oid(BigInteger input, byte[] out, int ooffset) {
        byte[] b = input.toByteArray();
        return pack7Oid(b, 0, b.length, out, ooffset);
    }

    /**
     * Private methods to check validity of OID. They must be --
     * 1. at least 2 components
     * 2. all components must be non-negative
     * 3. the first must be 0, 1 or 2
     * 4. if the first is 0 or 1, the second must be <40
     */

    /**
     * Check the DER encoding. Since DER encoding defines that the integer bits
     * are unsigned, so there's no need to check the MSB.
     */
    private static void check(byte[] encoding) throws IOException {
        int length = encoding.length;
        if (length < 1 ||      // too short
                (encoding[length - 1] & 0x80) != 0) {  // not ended
            throw new IOException("ObjectIdentifier() -- " +
                    "Invalid DER encoding, not ended");
        }
        for (int i=0; i<length; i++) {
            // 0x80 at the beginning of a subidentifier
            if (encoding[i] == (byte)0x80 &&
                    (i==0 || (encoding[i-1] & 0x80) == 0)) {
                throw new IOException("ObjectIdentifier() -- " +
                        "Invalid DER encoding, useless extra octet detected");
            }
        }
    }
    private static void checkCount(int count) throws IOException {
        if (count < 2) {
            throw new IOException("ObjectIdentifier() -- " +
                    "Must be at least two oid components ");
        }
    }
    private static void checkFirstComponent(int first) throws IOException {
        if (first < 0 || first > 2) {
            throw new IOException("ObjectIdentifier() -- " +
                    "First oid component is invalid ");
        }
    }
    private static void checkFirstComponent(BigInteger first) throws IOException {
        if (first.signum() == -1 ||
                first.compareTo(BigInteger.valueOf(2)) == 1) {
            throw new IOException("ObjectIdentifier() -- " +
                    "First oid component is invalid ");
        }
    }
    private static void checkSecondComponent(int first, int second) throws IOException {
        if (second < 0 || first != 2 && second > 39) {
            throw new IOException("ObjectIdentifier() -- " +
                    "Second oid component is invalid ");
        }
    }
    private static void checkSecondComponent(int first, BigInteger second) throws IOException {
        if (second.signum() == -1 ||
                first != 2 &&
                second.compareTo(BigInteger.valueOf(39)) == 1) {
            throw new IOException("ObjectIdentifier() -- " +
                    "Second oid component is invalid ");
        }
    }
    private static void checkOtherComponent(int i, int num) throws IOException {
        if (num < 0) {
            throw new IOException("ObjectIdentifier() -- " +
                    "oid component #" + (i+1) + " must be non-negative ");
        }
    }
    private static void checkOtherComponent(int i, BigInteger num) throws IOException {
        if (num.signum() == -1) {
            throw new IOException("ObjectIdentifier() -- " +
                    "oid component #" + (i+1) + " must be non-negative ");
        }
    }
}
