/*
 * Copyright (c) 2000, 2007, 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.jgss.krb5;

import org.ietf.jgss.*;
import sun.security.jgss.*;
import java.security.GeneralSecurityException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.IOException;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import sun.security.krb5.Confounder;
import sun.security.krb5.KrbException;

/**
 * This class represents a token emitted by the GSSContext.wrap()
 * call. It is a MessageToken except that it also contains plaintext
 * or encrypted data at the end. A wrapToken has certain other rules
 * that are peculiar to it and different from a MICToken, which is
 * another type of MessageToken. All data in a WrapToken is prepended
 * by a random counfounder of 8 bytes. All data in a WrapToken is
 * also padded with one to eight bytes where all bytes are equal in
 * value to the number of bytes being padded. Thus, all application
 * data is replaced by (confounder || data || padding).
 *
 * @author Mayank Upadhyay
 */
class WrapToken extends MessageToken {
    /**
     * The size of the random confounder used in a WrapToken.
     */
    static final int CONFOUNDER_SIZE = 8;

    /*
     * The padding used with a WrapToken. All data is padded to the
     * next multiple of 8 bytes, even if its length is already
     * multiple of 8.
     * Use this table as a quick way to obtain padding bytes by
     * indexing it with the number of padding bytes required.
     */
    static final byte[][] pads = {
        null, // No, no one escapes padding
        {0x01},
        {0x02, 0x02},
        {0x03, 0x03, 0x03},
        {0x04, 0x04, 0x04, 0x04},
        {0x05, 0x05, 0x05, 0x05, 0x05},
        {0x06, 0x06, 0x06, 0x06, 0x06, 0x06},
        {0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07},
        {0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08}
    };

    /*
     * A token may come in either in an InputStream or as a
     * byte[]. Store a reference to it in either case and process
     * it's data only later when getData() is called and
     * decryption/copying is needed to be done. Note that JCE can
     * decrypt both from a byte[] and from an InputStream.
     */
    private boolean readTokenFromInputStream = true;
    private InputStream is = null;
    private byte[] tokenBytes = null;
    private int tokenOffset = 0;
    private int tokenLen = 0;

    /*
     * Application data may come from an InputStream or from a
     * byte[]. However, it will always be stored and processed as a
     * byte[] since
     * (a) the MessageDigest class only accepts a byte[] as input and
     * (b) It allows writing to an OuputStream via a CipherOutputStream.
     */
    private byte[] dataBytes = null;
    private int dataOffset = 0;
    private int dataLen = 0;

    // the len of the token data: (confounder || data || padding)
    private int dataSize = 0;

    // Accessed by CipherHelper
    byte[] confounder = null;
    byte[] padding = null;

    private boolean privacy = false;

    /**
     * Constructs a WrapToken from token bytes obtained from the
     * peer.
     * @param context the mechanism context associated with this
     * token
     * @param tokenBytes the bytes of the token
     * @param tokenOffset the offset of the token
     * @param tokenLen the length of the token
     * @param prop the MessageProp into which characteristics of the
     * parsed token will be stored.
     * @throws GSSException if the token is defective
     */
    public WrapToken(Krb5Context context,
                     byte[] tokenBytes, int tokenOffset, int tokenLen,
                     MessageProp prop)  throws GSSException {

        // Just parse the MessageToken part first
        super(Krb5Token.WRAP_ID, context,
              tokenBytes, tokenOffset, tokenLen, prop);

        this.readTokenFromInputStream = false;

        // Will need the token bytes again when extracting data
        this.tokenBytes = tokenBytes;
        this.tokenOffset = tokenOffset;
        this.tokenLen = tokenLen;
        this.privacy = prop.getPrivacy();
        dataSize =
            getGSSHeader().getMechTokenLength() - getKrb5TokenSize();
    }

    /**
     * Constructs a WrapToken from token bytes read on the fly from
     * an InputStream.
     * @param context the mechanism context associated with this
     * token
     * @param is the InputStream containing the token bytes
     * @param prop the MessageProp into which characteristics of the
     * parsed token will be stored.
     * @throws GSSException if the token is defective or if there is
     * a problem reading from the InputStream
     */
    public WrapToken(Krb5Context context,
                     InputStream is, MessageProp prop)
        throws GSSException {

        // Just parse the MessageToken part first
        super(Krb5Token.WRAP_ID, context, is, prop);

        // Will need the token bytes again when extracting data
        this.is = is;
        this.privacy = prop.getPrivacy();
        /*
          debug("WrapToken Cons: gssHeader.getMechTokenLength=" +
          getGSSHeader().getMechTokenLength());
          debug("\n                token size="
          + getTokenSize());
        */

        dataSize =
            getGSSHeader().getMechTokenLength() - getTokenSize();
        // debug("\n                dataSize=" + dataSize);
        // debug("\n");
    }

    /**
     * Obtains the application data that was transmitted in this
     * WrapToken.
     * @return a byte array containing the application data
     * @throws GSSException if an error occurs while decrypting any
     * cipher text and checking for validity
     */
    public byte[] getData() throws GSSException {

        byte[] temp = new byte[dataSize];
        getData(temp, 0);

        // Remove the confounder and the padding
        byte[] retVal = new byte[dataSize - confounder.length -
                                padding.length];
        System.arraycopy(temp, 0, retVal, 0, retVal.length);

        return retVal;
    }

    /**
     * Obtains the application data that was transmitted in this
     * WrapToken, writing it into an application provided output
     * array.
     * @param dataBuf the output buffer into which the data must be
     * written
     * @param dataBufOffset the offset at which to write the data
     * @return the size of the data written
     * @throws GSSException if an error occurs while decrypting any
     * cipher text and checking for validity
     */
    public int getData(byte[] dataBuf, int dataBufOffset)
        throws GSSException {

        if (readTokenFromInputStream)
            getDataFromStream(dataBuf, dataBufOffset);
        else
            getDataFromBuffer(dataBuf, dataBufOffset);

        return (dataSize - confounder.length - padding.length);
    }

    /**
     * Helper routine to obtain the application data transmitted in
     * this WrapToken. It is called if the WrapToken was constructed
     * with a byte array as input.
     * @param dataBuf the output buffer into which the data must be
     * written
     * @param dataBufOffset the offset at which to write the data
     * @throws GSSException if an error occurs while decrypting any
     * cipher text and checking for validity
     */
    private void getDataFromBuffer(byte[] dataBuf, int dataBufOffset)
        throws GSSException {

        GSSHeader gssHeader = getGSSHeader();
        int dataPos = tokenOffset +
            gssHeader.getLength() + getTokenSize();

        if (dataPos + dataSize > tokenOffset + tokenLen)
            throw new GSSException(GSSException.DEFECTIVE_TOKEN, -1,
                                   "Insufficient data in "
                                   + getTokenName(getTokenId()));

        // debug("WrapToken cons: data is token is [" +
        //      getHexBytes(tokenBytes, tokenOffset, tokenLen) + "]\n");

        confounder = new byte[CONFOUNDER_SIZE];

        // Do decryption if this token was privacy protected.

        if (privacy) {
            cipherHelper.decryptData(this,
                tokenBytes, dataPos, dataSize, dataBuf, dataBufOffset);
            /*
            debug("\t\tDecrypted data is [" +
                getHexBytes(confounder) + " " +
                getHexBytes(dataBuf, dataBufOffset,
                        dataSize - CONFOUNDER_SIZE - padding.length) +
                getHexBytes(padding) +
            "]\n");
            */

        } else {

            // Token data is in cleartext
            // debug("\t\tNo encryption was performed by peer.\n");
            System.arraycopy(tokenBytes, dataPos,
                             confounder, 0, CONFOUNDER_SIZE);
            int padSize = tokenBytes[dataPos + dataSize - 1];
            if (padSize < 0)
                padSize = 0;
            if (padSize > 8)
                padSize %= 8;

            padding = pads[padSize];
            // debug("\t\tPadding applied was: " + padSize + "\n");

            System.arraycopy(tokenBytes, dataPos + CONFOUNDER_SIZE,
                             dataBuf, dataBufOffset, dataSize -
                             CONFOUNDER_SIZE - padSize);

           // byte[] debugbuf = new byte[dataSize - CONFOUNDER_SIZE - padSize];
           // System.arraycopy(tokenBytes, dataPos + CONFOUNDER_SIZE,
           //                debugbuf, 0, debugbuf.length);
           // debug("\t\tData is: " + getHexBytes(debugbuf, debugbuf.length));
        }

        /*
         * Make sure sign and sequence number are not corrupt
         */

        if (!verifySignAndSeqNumber(confounder,
                                    dataBuf, dataBufOffset,
                                    dataSize - CONFOUNDER_SIZE
                                    - padding.length,
                                    padding))
            throw new GSSException(GSSException.BAD_MIC, -1,
                         "Corrupt checksum or sequence number in Wrap token");
    }

    /**
     * Helper routine to obtain the application data transmitted in
     * this WrapToken. It is called if the WrapToken was constructed
     * with an Inputstream.
     * @param dataBuf the output buffer into which the data must be
     * written
     * @param dataBufOffset the offset at which to write the data
     * @throws GSSException if an error occurs while decrypting any
     * cipher text and checking for validity
     */
    private void getDataFromStream(byte[] dataBuf, int dataBufOffset)
        throws GSSException {

        GSSHeader gssHeader = getGSSHeader();

        // Don't check the token length. Data will be read on demand from
        // the InputStream.

        // debug("WrapToken cons: data will be read from InputStream.\n");

        confounder = new byte[CONFOUNDER_SIZE];

        try {

            // Do decryption if this token was privacy protected.

            if (privacy) {
                cipherHelper.decryptData(this, is, dataSize,
                    dataBuf, dataBufOffset);

                // debug("\t\tDecrypted data is [" +
                //     getHexBytes(confounder) + " " +
                //     getHexBytes(dataBuf, dataBufOffset,
                // dataSize - CONFOUNDER_SIZE - padding.length) +
                //     getHexBytes(padding) +
                //     "]\n");

            } else {

                // Token data is in cleartext
                // debug("\t\tNo encryption was performed by peer.\n");
                readFully(is, confounder);

                // Data is always a multiple of 8 with this GSS Mech
                // Copy all but last block as they are
                int numBlocks = (dataSize - CONFOUNDER_SIZE)/8 - 1;
                int offset = dataBufOffset;
                for (int i = 0; i < numBlocks; i++) {
                    readFully(is, dataBuf, offset, 8);
                    offset += 8;
                }

                byte[] finalBlock = new byte[8];
                readFully(is, finalBlock);

                int padSize = finalBlock[7];
                padding = pads[padSize];

                // debug("\t\tPadding applied was: " + padSize + "\n");
                System.arraycopy(finalBlock, 0, dataBuf, offset,
                                 finalBlock.length - padSize);
            }
        } catch (IOException e) {
            throw new GSSException(GSSException.DEFECTIVE_TOKEN, -1,
                                   getTokenName(getTokenId())
                                   + ": " + e.getMessage());
        }

        /*
         * Make sure sign and sequence number are not corrupt
         */

        if (!verifySignAndSeqNumber(confounder,
                                    dataBuf, dataBufOffset,
                                    dataSize - CONFOUNDER_SIZE
                                    - padding.length,
                                    padding))
            throw new GSSException(GSSException.BAD_MIC, -1,
                         "Corrupt checksum or sequence number in Wrap token");
    }


    /**
     * Helper routine to pick the right padding for a certain length
     * of application data. Every application message has some
     * padding between 1 and 8 bytes.
     * @param len the length of the application data
     * @return the padding to be applied
     */
    private byte[] getPadding(int len) {
        int padSize = 0;
        // For RC4-HMAC, all padding is rounded up to 1 byte.
        // One byte is needed to say that there is 1 byte of padding.
        if (cipherHelper.isArcFour()) {
            padSize = 1;
        } else {
            padSize = len % 8;
            padSize = 8 - padSize;
        }
        return pads[padSize];
    }

    public WrapToken(Krb5Context context, MessageProp prop,
                     byte[] dataBytes, int dataOffset, int dataLen)
        throws GSSException {

        super(Krb5Token.WRAP_ID, context);

        confounder = Confounder.bytes(CONFOUNDER_SIZE);

        padding = getPadding(dataLen);
        dataSize = confounder.length + dataLen + padding.length;
        this.dataBytes = dataBytes;
        this.dataOffset = dataOffset;
        this.dataLen = dataLen;

        /*
          debug("\nWrapToken cons: data to wrap is [" +
          getHexBytes(confounder) + " " +
          getHexBytes(dataBytes, dataOffset, dataLen) + " " +
          // padding is never null for Wrap
          getHexBytes(padding) + "]\n");
         */

        genSignAndSeqNumber(prop,
                            confounder,
                            dataBytes, dataOffset, dataLen,
                            padding);

        /*
         * If the application decides to ask for privacy when the context
         * did not negotiate for it, do not provide it. The peer might not
         * have support for it. The app will realize this with a call to
         * pop.getPrivacy() after wrap().
         */
        if (!context.getConfState())
            prop.setPrivacy(false);

        privacy = prop.getPrivacy();
    }

    public void encode(OutputStream os) throws IOException, GSSException {

        super.encode(os);

        // debug("Writing data: [");
        if (!privacy) {

            // debug(getHexBytes(confounder, confounder.length));
            os.write(confounder);

            // debug(" " + getHexBytes(dataBytes, dataOffset, dataLen));
            os.write(dataBytes, dataOffset, dataLen);

            // debug(" " + getHexBytes(padding, padding.length));
            os.write(padding);

        } else {

            cipherHelper.encryptData(this, confounder,
                dataBytes, dataOffset, dataLen, padding, os);
        }
        // debug("]\n");
    }

    public byte[] encode() throws IOException, GSSException {
        // XXX Fine tune this initial size
        ByteArrayOutputStream bos = new ByteArrayOutputStream(dataSize + 50);
        encode(bos);
        return bos.toByteArray();
    }

    public int encode(byte[] outToken, int offset)
        throws IOException, GSSException  {

        // Token header is small
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        super.encode(bos);
        byte[] header = bos.toByteArray();
        System.arraycopy(header, 0, outToken, offset, header.length);
        offset += header.length;

        // debug("WrapToken.encode: Writing data: [");
        if (!privacy) {

            // debug(getHexBytes(confounder, confounder.length));
            System.arraycopy(confounder, 0, outToken, offset,
                             confounder.length);
            offset += confounder.length;

            // debug(" " + getHexBytes(dataBytes, dataOffset, dataLen));
            System.arraycopy(dataBytes, dataOffset, outToken, offset,
                             dataLen);
            offset += dataLen;

            // debug(" " + getHexBytes(padding, padding.length));
            System.arraycopy(padding, 0, outToken, offset, padding.length);

        } else {

            cipherHelper.encryptData(this, confounder, dataBytes,
                dataOffset, dataLen, padding, outToken, offset);

            // debug(getHexBytes(outToken, offset, dataSize));
        }

        // debug("]\n");

        // %%% assume that plaintext length == ciphertext len
        return (header.length + confounder.length + dataLen + padding.length);

    }

    protected int getKrb5TokenSize() throws GSSException {
        return (getTokenSize() + dataSize);
    }

    protected int getSealAlg(boolean conf, int qop) throws GSSException {
        if (!conf) {
            return SEAL_ALG_NONE;
        }

        // ignore QOP
        return cipherHelper.getSealAlg();
    }

    // This implementation is way too conservative. And it certainly
    // doesn't return the maximum limit.
    static int getSizeLimit(int qop, boolean confReq, int maxTokenSize,
        CipherHelper ch) throws GSSException {
        return (GSSHeader.getMaxMechTokenSize(OID, maxTokenSize) -
                (getTokenSize(ch) + CONFOUNDER_SIZE) - 8); /* safety */
    }

}
