/*
 *  Licensed to the Apache Software Foundation (ASF) under one
 *  or more contributor license agreements.  See the NOTICE file
 *  distributed with this work for additional information
 *  regarding copyright ownership.  The ASF licenses this file
 *  to you under the Apache License, Version 2.0 (the
 *  "License"); you may not use this file except in compliance
 *  with the License.  You may obtain a copy of the License at
 *  
 *    http://www.apache.org/licenses/LICENSE-2.0
 *  
 *  Unless required by applicable law or agreed to in writing,
 *  software distributed under the License is distributed on an
 *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 *  KIND, either express or implied.  See the License for the
 *  specific language governing permissions and limitations
 *  under the License. 
 *  
 */
package org.apache.directory.server.kerberos.shared.crypto.encryption;


import java.security.SecureRandom;

import org.apache.directory.server.kerberos.shared.exceptions.KerberosException;
import org.apache.directory.server.kerberos.shared.messages.value.EncryptedData;
import org.apache.directory.server.kerberos.shared.messages.value.EncryptionKey;


/**
 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
 * @version $Rev$, $Date$
 */
public abstract class EncryptionEngine
{
    private static final SecureRandom random = new SecureRandom();


    protected abstract byte[] getDecryptedData( EncryptionKey key, EncryptedData data, KeyUsage usage )
        throws KerberosException;


    protected abstract EncryptedData getEncryptedData( EncryptionKey key, byte[] plainText, KeyUsage usage );


    protected abstract EncryptionType getEncryptionType();


    protected abstract int getConfounderLength();


    protected abstract int getChecksumLength();


    protected abstract byte[] encrypt( byte[] plainText, byte[] key );


    protected abstract byte[] decrypt( byte[] cipherText, byte[] key );


    protected abstract byte[] calculateIntegrity( byte[] plainText, byte[] key, KeyUsage usage );


    protected byte[] deriveRandom( byte[] key, byte[] usage, int n, int k )
    {
        byte[] nFoldedUsage = NFold.nFold( n, usage );

        int kBytes = k / 8;
        byte[] result = new byte[kBytes];

        byte[] fillingKey = encrypt( nFoldedUsage, key );

        int pos = 0;

        for ( int i = 0; i < kBytes; i++ )
        {
            if ( pos < fillingKey.length )
            {
                result[i] = fillingKey[pos];
                pos++;
            }
            else
            {
                fillingKey = encrypt( fillingKey, key );
                pos = 0;
                result[i] = fillingKey[pos];
                pos++;
            }
        }

        return result;
    }


    // Encryption
    protected byte[] getRandomBytes( int size )
    {
        byte[] bytes = new byte[size];

        // SecureRandom.nextBytes is already synchronized
        random.nextBytes( bytes );

        return bytes;
    }


    // Encryption
    protected byte[] padString( byte encodedString[] )
    {
        int x;
        if ( encodedString.length < 8 )
        {
            x = encodedString.length;
        }
        else
        {
            x = encodedString.length % 8;
        }

        if ( x == 0 )
        {
            return encodedString;
        }

        byte paddedByteArray[] = new byte[( 8 - x ) + encodedString.length];

        for ( int y = paddedByteArray.length - 1; y > encodedString.length - 1; y-- )
        {
            paddedByteArray[y] = 0;
        }

        System.arraycopy( encodedString, 0, paddedByteArray, 0, encodedString.length );

        return paddedByteArray;
    }


    // Encryption
    protected byte[] concatenateBytes( byte[] array1, byte[] array2 )
    {
        byte concatenatedBytes[] = new byte[array1.length + array2.length];

        for ( int i = 0; i < array1.length; i++ )
        {
            concatenatedBytes[i] = array1[i];
        }

        for ( int j = array1.length; j < concatenatedBytes.length; j++ )
        {
            concatenatedBytes[j] = array2[j - array1.length];
        }

        return concatenatedBytes;
    }


    // Decryption
    protected byte[] removeLeadingBytes( byte[] array, int confounder, int checksum )
    {
        byte lessBytes[] = new byte[array.length - confounder - checksum];

        int j = 0;
        for ( int i = confounder + checksum; i < array.length; i++ )
        {
            lessBytes[j] = array[i];
            j++;
        }

        return lessBytes;
    }


    protected byte[] removeTrailingBytes( byte[] array, int confounder, int checksum )
    {
        byte lessBytes[] = new byte[array.length - confounder - checksum];

        int j = 0;
        for ( int i = 0; i < array.length - confounder - checksum; i++ )
        {
            lessBytes[j] = array[i];
            j++;
        }

        return lessBytes;
    }


    protected int getBit( byte[] data, int pos )
    {
        int posByte = pos / 8;
        int posBit = pos % 8;

        byte valByte = data[posByte];
        int valInt = valByte >> ( 8 - ( posBit + 1 ) ) & 0x0001;
        return valInt;
    }


    protected void setBit( byte[] data, int pos, int val )
    {
        int posByte = pos / 8;
        int posBit = pos % 8;
        byte oldByte = data[posByte];
        oldByte = ( byte ) ( ( ( 0xFF7F >> posBit ) & oldByte ) & 0x00FF );
        byte newByte = ( byte ) ( ( val << ( 8 - ( posBit + 1 ) ) ) | oldByte );
        data[posByte] = newByte;
    }


    /**
     * The "well-known constant" used for the DK function is the key
     * usage number, expressed as four octets in big-endian order,
     * followed by one octet indicated below.
     * 
     *  Kc = DK(base-key, usage | 0x99);
     */
    protected byte[] getUsageKc( KeyUsage usage )
    {
        return getUsage( usage.getOrdinal(), ( byte ) 0x99 );
    }


    /**
     * The "well-known constant" used for the DK function is the key
     * usage number, expressed as four octets in big-endian order,
     * followed by one octet indicated below.
     * 
     *  Ke = DK(base-key, usage | 0xAA);
     */
    protected byte[] getUsageKe( KeyUsage usage )
    {
        return getUsage( usage.getOrdinal(), ( byte ) 0xAA );
    }


    /**
     * The "well-known constant" used for the DK function is the key
     * usage number, expressed as four octets in big-endian order,
     * followed by one octet indicated below.
     * 
     *  Ki = DK(base-key, usage | 0x55);
     */
    protected byte[] getUsageKi( KeyUsage usage )
    {
        return getUsage( usage.getOrdinal(), ( byte ) 0x55 );
    }


    private byte[] getUsage( int usage, byte constant )
    {
        byte[] bytes = new byte[5];
        bytes[0] = ( byte ) ( ( usage >>> 24 ) & 0x000000FF );
        bytes[1] = ( byte ) ( ( usage >> 16 ) & 0x000000FF );
        bytes[2] = ( byte ) ( ( usage >> 8 ) & 0x000000FF );
        bytes[3] = ( byte ) ( usage & 0x00FF );
        bytes[4] = constant;

        return bytes;
    }
}
