/*
 * Portions Copyright 2000-2007 Sun Microsystems, Inc.  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.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

/*
 *
 *  (C) Copyright IBM Corp. 1999 All Rights Reserved.
 *  Copyright 1997 The Open Group Research Institute.  All rights reserved.
 */

package sun.security.krb5.internal.crypto;

import sun.security.krb5.Confounder;
import sun.security.krb5.KrbCryptoException;
import sun.security.krb5.internal.*;

abstract class DesCbcEType extends EType {
    protected abstract byte[] calculateChecksum(byte[] data, int size)
        throws KrbCryptoException;

    public int blockSize() {
        return 8;
    }

    public int keyType() {
        return Krb5.KEYTYPE_DES;
    }

    public int keySize() {
        return 8;
    }

    /**
     * Encrypts the data using DES in CBC mode.
     * @param data the buffer for plain text.
     * @param key the key to encrypt the data.
     * @return the buffer for encrypted data.
     *
     * @written by Yanni Zhang, Dec 6 99.
     */

    public byte[] encrypt(byte[] data, byte[] key, int usage)
         throws KrbCryptoException {
        byte[] ivec = new byte[keySize()];
        return encrypt(data, key, ivec, usage);
    }

    /**
     * Encrypts the data using DES in CBC mode.
     * @param data the buffer for plain text.
     * @param key the key to encrypt the data.
     * @param ivec initialization vector.
     * @return buffer for encrypted data.
     *
     * @modified by Yanni Zhang, Feb 24 00.
     */
    public byte[] encrypt(byte[] data, byte[] key, byte[] ivec,
        int usage) throws KrbCryptoException {

        /*
         * To meet export control requirements, double check that the
         * key being used is no longer than 64 bits.
         *
         * Note that from a protocol point of view, an
         * algorithm that is not DES will be rejected before this
         * point. Also, a  DES key that is not 64 bits will be
         * rejected by a good implementations of JCE.
         */
        if (key.length > 8)
        throw new KrbCryptoException("Invalid DES Key!");

        int new_size = data.length + confounderSize() + checksumSize();
        byte[] new_data;
        byte pad;
        /*Data padding: using Kerberos 5 GSS-API mechanism (1.2.2.3), Jun 1996.
         *Before encryption, plaintext data is padded to the next higest multiple of blocksize.
         *by appending between 1 and 8 bytes, the value of each such byte being the total number
         *of pad bytes. For example, if new_size = 10, blockSize is 8, we should pad 2 bytes,
         *and the value of each byte is 2.
         *If plaintext data is a multiple of blocksize, we pad a 8 bytes of 8.
         */
        if (new_size % blockSize() == 0) {
            new_data = new byte[new_size + blockSize()];
            pad = (byte)8;
        }
        else {
            new_data = new byte[new_size + blockSize() - new_size % blockSize()];
            pad = (byte)(blockSize() - new_size % blockSize());
        }
        for (int i = new_size; i < new_data.length; i++) {
            new_data[i] = pad;
        }
        byte[] conf = Confounder.bytes(confounderSize());
        System.arraycopy(conf, 0, new_data, 0, confounderSize());
        System.arraycopy(data, 0, new_data, startOfData(), data.length);
        byte[] cksum = calculateChecksum(new_data, new_data.length);
        System.arraycopy(cksum, 0, new_data, startOfChecksum(),
                         checksumSize());
        byte[] cipher = new byte[new_data.length];
        Des.cbc_encrypt(new_data, cipher, key, ivec, true);
        return cipher;
    }

    /**
     * Decrypts the data using DES in CBC mode.
     * @param cipher the input buffer.
     * @param key the key to decrypt the data.
     *
     * @written by Yanni Zhang, Dec 6 99.
     */
    public byte[] decrypt(byte[] cipher, byte[] key, int usage)
        throws KrbApErrException, KrbCryptoException{
        byte[] ivec = new byte[keySize()];
        return decrypt(cipher, key, ivec, usage);
    }

    /**
     * Decrypts the data using DES in CBC mode.
     * @param cipher the input buffer.
     * @param key the key to decrypt the data.
     * @param ivec initialization vector.
     *
     * @modified by Yanni Zhang, Dec 6 99.
     */
    public byte[] decrypt(byte[] cipher, byte[] key, byte[] ivec, int usage)
        throws KrbApErrException, KrbCryptoException {

        /*
         * To meet export control requirements, double check that the
         * key being used is no longer than 64 bits.
         *
         * Note that from a protocol point of view, an
         * algorithm that is not DES will be rejected before this
         * point. Also, a DES key that is not 64 bits will be
         * rejected by a good JCE provider.
         */
        if (key.length > 8)
            throw new KrbCryptoException("Invalid DES Key!");

        byte[] data = new byte[cipher.length];
        Des.cbc_encrypt(cipher, data, key, ivec, false);
        if (!isChecksumValid(data))
            throw new KrbApErrException(Krb5.KRB_AP_ERR_BAD_INTEGRITY);
        return data;
    }

    private void copyChecksumField(byte[] data, byte[] cksum) {
        for (int i = 0; i < checksumSize();  i++)
            data[startOfChecksum() + i] = cksum[i];
    }

    private byte[] checksumField(byte[] data) {
        byte[] result = new byte[checksumSize()];
        for (int i = 0; i < checksumSize(); i++)
        result[i] = data[startOfChecksum() + i];
        return result;
    }

    private void resetChecksumField(byte[] data) {
        for (int i = startOfChecksum(); i < startOfChecksum() +
                 checksumSize();  i++)
            data[i] = 0;
    }

    /*
        // Not used.
    public void setChecksum(byte[] data, int size) throws KrbCryptoException{
        resetChecksumField(data);
        byte[] cksum = calculateChecksum(data, size);
        copyChecksumField(data, cksum);
    }
*/

    private byte[] generateChecksum(byte[] data) throws KrbCryptoException{
        byte[] cksum1 = checksumField(data);
        resetChecksumField(data);
        byte[] cksum2 = calculateChecksum(data, data.length);
        copyChecksumField(data, cksum1);
        return cksum2;
    }

    private boolean isChecksumEqual(byte[] cksum1, byte[] cksum2) {
        if (cksum1 == cksum2)
            return true;
        if ((cksum1 == null && cksum2 != null) ||
            (cksum1 != null && cksum2 == null))
            return false;
        if (cksum1.length != cksum2.length)
            return false;
        for (int i = 0; i < cksum1.length; i++)
            if (cksum1[i] != cksum2[i])
                return false;
        return true;
    }

    protected boolean isChecksumValid(byte[] data) throws KrbCryptoException {
        byte[] cksum1 = checksumField(data);
        byte[] cksum2 = generateChecksum(data);
        return isChecksumEqual(cksum1, cksum2);
    }
}
