// 
// Decompiled by Procyon v0.6.0
// 

package org.bouncycastle.crypto.engines;

import org.bouncycastle.util.encoders.Hex;
import org.bouncycastle.util.Bytes;
import org.bouncycastle.crypto.OutputLengthException;
import org.bouncycastle.crypto.DataLengthException;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.CryptoServiceProperties;
import org.bouncycastle.crypto.CryptoServicesRegistrar;
import org.bouncycastle.crypto.constraints.DefaultServiceProperties;
import org.bouncycastle.crypto.BlockCipher;

public class ARIAEngine implements BlockCipher
{
    private static final byte[][] C;
    private static final byte[] SB1_sbox;
    private static final byte[] SB2_sbox;
    private static final byte[] SB3_sbox;
    private static final byte[] SB4_sbox;
    protected static final int BLOCK_SIZE = 16;
    private byte[][] roundKeys;
    boolean forEncryption;
    
    public ARIAEngine() {
        CryptoServicesRegistrar.checkConstraints(new DefaultServiceProperties(this.getAlgorithmName(), 256));
    }
    
    @Override
    public void init(final boolean forEncryption, final CipherParameters cipherParameters) throws IllegalArgumentException {
        if (!(cipherParameters instanceof KeyParameter)) {
            throw new IllegalArgumentException("invalid parameter passed to ARIA init - " + cipherParameters.getClass().getName());
        }
        this.forEncryption = forEncryption;
        this.roundKeys = keySchedule(forEncryption, ((KeyParameter)cipherParameters).getKey());
        CryptoServicesRegistrar.checkConstraints(new DefaultServiceProperties(this.getAlgorithmName(), this.bitsOfSecurity(), cipherParameters, Utils.getPurpose(forEncryption)));
    }
    
    @Override
    public String getAlgorithmName() {
        return "ARIA";
    }
    
    @Override
    public int getBlockSize() {
        return 16;
    }
    
    @Override
    public int processBlock(final byte[] array, final int n, final byte[] array2, final int n2) throws DataLengthException, IllegalStateException {
        if (this.roundKeys == null) {
            throw new IllegalStateException("ARIA engine not initialised");
        }
        if (n > array.length - 16) {
            throw new DataLengthException("input buffer too short");
        }
        if (n2 > array2.length - 16) {
            throw new OutputLengthException("output buffer too short");
        }
        final byte[] array3 = new byte[16];
        System.arraycopy(array, n, array3, 0, 16);
        int i = 0;
        while (i < this.roundKeys.length - 3) {
            FO(array3, this.roundKeys[i++]);
            FE(array3, this.roundKeys[i++]);
        }
        FO(array3, this.roundKeys[i++]);
        xor(array3, this.roundKeys[i++]);
        SL2(array3);
        xor(array3, this.roundKeys[i]);
        System.arraycopy(array3, 0, array2, n2, 16);
        return 16;
    }
    
    @Override
    public void reset() {
    }
    
    protected static void A(final byte[] array) {
        final byte b = array[0];
        final byte b2 = array[1];
        final byte b3 = array[2];
        final byte b4 = array[3];
        final byte b5 = array[4];
        final byte b6 = array[5];
        final byte b7 = array[6];
        final byte b8 = array[7];
        final byte b9 = array[8];
        final byte b10 = array[9];
        final byte b11 = array[10];
        final byte b12 = array[11];
        final byte b13 = array[12];
        final byte b14 = array[13];
        final byte b15 = array[14];
        final byte b16 = array[15];
        array[0] = (byte)(b4 ^ b5 ^ b7 ^ b9 ^ b10 ^ b14 ^ b15);
        array[1] = (byte)(b3 ^ b6 ^ b8 ^ b9 ^ b10 ^ b13 ^ b16);
        array[2] = (byte)(b2 ^ b5 ^ b7 ^ b11 ^ b12 ^ b13 ^ b16);
        array[3] = (byte)(b ^ b6 ^ b8 ^ b11 ^ b12 ^ b14 ^ b15);
        array[4] = (byte)(b ^ b3 ^ b6 ^ b9 ^ b12 ^ b15 ^ b16);
        array[5] = (byte)(b2 ^ b4 ^ b5 ^ b10 ^ b11 ^ b15 ^ b16);
        array[6] = (byte)(b ^ b3 ^ b8 ^ b10 ^ b11 ^ b13 ^ b14);
        array[7] = (byte)(b2 ^ b4 ^ b7 ^ b9 ^ b12 ^ b13 ^ b14);
        array[8] = (byte)(b ^ b2 ^ b5 ^ b8 ^ b11 ^ b14 ^ b16);
        array[9] = (byte)(b ^ b2 ^ b6 ^ b7 ^ b12 ^ b13 ^ b15);
        array[10] = (byte)(b3 ^ b4 ^ b6 ^ b7 ^ b9 ^ b14 ^ b16);
        array[11] = (byte)(b3 ^ b4 ^ b5 ^ b8 ^ b10 ^ b13 ^ b15);
        array[12] = (byte)(b2 ^ b3 ^ b7 ^ b8 ^ b10 ^ b12 ^ b13);
        array[13] = (byte)(b ^ b4 ^ b7 ^ b8 ^ b9 ^ b11 ^ b14);
        array[14] = (byte)(b ^ b4 ^ b5 ^ b6 ^ b10 ^ b12 ^ b15);
        array[15] = (byte)(b2 ^ b3 ^ b5 ^ b6 ^ b9 ^ b11 ^ b16);
    }
    
    protected static void FE(final byte[] array, final byte[] array2) {
        xor(array, array2);
        SL2(array);
        A(array);
    }
    
    protected static void FO(final byte[] array, final byte[] array2) {
        xor(array, array2);
        SL1(array);
        A(array);
    }
    
    protected static byte[][] keySchedule(final boolean b, final byte[] array) {
        final int length = array.length;
        if (length < 16 || length > 32 || (length & 0x7) != 0x0) {
            throw new IllegalArgumentException("Key length not 128/192/256 bits.");
        }
        final int n = (length >>> 3) - 2;
        final byte[] array2 = ARIAEngine.C[n];
        final byte[] array3 = ARIAEngine.C[(n + 1) % 3];
        final byte[] array4 = ARIAEngine.C[(n + 2) % 3];
        final byte[] array5 = new byte[16];
        final byte[] array6 = new byte[16];
        System.arraycopy(array, 0, array5, 0, 16);
        System.arraycopy(array, 16, array6, 0, length - 16);
        final byte[] array7 = new byte[16];
        final byte[] array8 = new byte[16];
        final byte[] array9 = new byte[16];
        final byte[] array10 = new byte[16];
        System.arraycopy(array5, 0, array7, 0, 16);
        System.arraycopy(array7, 0, array8, 0, 16);
        FO(array8, array2);
        xor(array8, array6);
        System.arraycopy(array8, 0, array9, 0, 16);
        FE(array9, array3);
        xor(array9, array7);
        System.arraycopy(array9, 0, array10, 0, 16);
        FO(array10, array4);
        xor(array10, array8);
        final int n2 = 12 + n * 2;
        final byte[][] array11 = new byte[n2 + 1][16];
        keyScheduleRound(array11[0], array7, array8, 19);
        keyScheduleRound(array11[1], array8, array9, 19);
        keyScheduleRound(array11[2], array9, array10, 19);
        keyScheduleRound(array11[3], array10, array7, 19);
        keyScheduleRound(array11[4], array7, array8, 31);
        keyScheduleRound(array11[5], array8, array9, 31);
        keyScheduleRound(array11[6], array9, array10, 31);
        keyScheduleRound(array11[7], array10, array7, 31);
        keyScheduleRound(array11[8], array7, array8, 67);
        keyScheduleRound(array11[9], array8, array9, 67);
        keyScheduleRound(array11[10], array9, array10, 67);
        keyScheduleRound(array11[11], array10, array7, 67);
        keyScheduleRound(array11[12], array7, array8, 97);
        if (n2 > 12) {
            keyScheduleRound(array11[13], array8, array9, 97);
            keyScheduleRound(array11[14], array9, array10, 97);
            if (n2 > 14) {
                keyScheduleRound(array11[15], array10, array7, 97);
                keyScheduleRound(array11[16], array7, array8, 109);
            }
        }
        if (!b) {
            reverseKeys(array11);
            for (int i = 1; i < n2; ++i) {
                A(array11[i]);
            }
        }
        return array11;
    }
    
    protected static void keyScheduleRound(final byte[] array, final byte[] array2, final byte[] array3, final int n) {
        final int n2 = n >>> 3;
        final int n3 = n & 0x7;
        final int n4 = 8 - n3;
        int n5 = array3[15 - n2] & 0xFF;
        for (int i = 0; i < 16; ++i) {
            final int n6 = array3[i - n2 & 0xF] & 0xFF;
            array[i] = (byte)((n5 << n4 | n6 >>> n3) ^ (array2[i] & 0xFF));
            n5 = n6;
        }
    }
    
    protected static void reverseKeys(final byte[][] array) {
        final int length = array.length;
        final int n = length / 2;
        final int n2 = length - 1;
        for (int i = 0; i < n; ++i) {
            final byte[] array2 = array[i];
            array[i] = array[n2 - i];
            array[n2 - i] = array2;
        }
    }
    
    protected static byte SB1(final byte b) {
        return ARIAEngine.SB1_sbox[b & 0xFF];
    }
    
    protected static byte SB2(final byte b) {
        return ARIAEngine.SB2_sbox[b & 0xFF];
    }
    
    protected static byte SB3(final byte b) {
        return ARIAEngine.SB3_sbox[b & 0xFF];
    }
    
    protected static byte SB4(final byte b) {
        return ARIAEngine.SB4_sbox[b & 0xFF];
    }
    
    protected static void SL1(final byte[] array) {
        array[0] = SB1(array[0]);
        array[1] = SB2(array[1]);
        array[2] = SB3(array[2]);
        array[3] = SB4(array[3]);
        array[4] = SB1(array[4]);
        array[5] = SB2(array[5]);
        array[6] = SB3(array[6]);
        array[7] = SB4(array[7]);
        array[8] = SB1(array[8]);
        array[9] = SB2(array[9]);
        array[10] = SB3(array[10]);
        array[11] = SB4(array[11]);
        array[12] = SB1(array[12]);
        array[13] = SB2(array[13]);
        array[14] = SB3(array[14]);
        array[15] = SB4(array[15]);
    }
    
    protected static void SL2(final byte[] array) {
        array[0] = SB3(array[0]);
        array[1] = SB4(array[1]);
        array[2] = SB1(array[2]);
        array[3] = SB2(array[3]);
        array[4] = SB3(array[4]);
        array[5] = SB4(array[5]);
        array[6] = SB1(array[6]);
        array[7] = SB2(array[7]);
        array[8] = SB3(array[8]);
        array[9] = SB4(array[9]);
        array[10] = SB1(array[10]);
        array[11] = SB2(array[11]);
        array[12] = SB3(array[12]);
        array[13] = SB4(array[13]);
        array[14] = SB1(array[14]);
        array[15] = SB2(array[15]);
    }
    
    protected static void xor(final byte[] array, final byte[] array2) {
        Bytes.xorTo(16, array2, array);
    }
    
    private int bitsOfSecurity() {
        return (this.roundKeys.length > 13) ? ((this.roundKeys.length > 15) ? 256 : 192) : 128;
    }
    
    static {
        C = new byte[][] { Hex.decodeStrict("517cc1b727220a94fe13abe8fa9a6ee0"), Hex.decodeStrict("6db14acc9e21c820ff28b1d5ef5de2b0"), Hex.decodeStrict("db92371d2126e9700324977504e8c90e") };
        SB1_sbox = new byte[] { 99, 124, 119, 123, -14, 107, 111, -59, 48, 1, 103, 43, -2, -41, -85, 118, -54, -126, -55, 125, -6, 89, 71, -16, -83, -44, -94, -81, -100, -92, 114, -64, -73, -3, -109, 38, 54, 63, -9, -52, 52, -91, -27, -15, 113, -40, 49, 21, 4, -57, 35, -61, 24, -106, 5, -102, 7, 18, -128, -30, -21, 39, -78, 117, 9, -125, 44, 26, 27, 110, 90, -96, 82, 59, -42, -77, 41, -29, 47, -124, 83, -47, 0, -19, 32, -4, -79, 91, 106, -53, -66, 57, 74, 76, 88, -49, -48, -17, -86, -5, 67, 77, 51, -123, 69, -7, 2, 127, 80, 60, -97, -88, 81, -93, 64, -113, -110, -99, 56, -11, -68, -74, -38, 33, 16, -1, -13, -46, -51, 12, 19, -20, 95, -105, 68, 23, -60, -89, 126, 61, 100, 93, 25, 115, 96, -127, 79, -36, 34, 42, -112, -120, 70, -18, -72, 20, -34, 94, 11, -37, -32, 50, 58, 10, 73, 6, 36, 92, -62, -45, -84, 98, -111, -107, -28, 121, -25, -56, 55, 109, -115, -43, 78, -87, 108, 86, -12, -22, 101, 122, -82, 8, -70, 120, 37, 46, 28, -90, -76, -58, -24, -35, 116, 31, 75, -67, -117, -118, 112, 62, -75, 102, 72, 3, -10, 14, 97, 53, 87, -71, -122, -63, 29, -98, -31, -8, -104, 17, 105, -39, -114, -108, -101, 30, -121, -23, -50, 85, 40, -33, -116, -95, -119, 13, -65, -26, 66, 104, 65, -103, 45, 15, -80, 84, -69, 22 };
        SB2_sbox = new byte[] { -30, 78, 84, -4, -108, -62, 74, -52, 98, 13, 106, 70, 60, 77, -117, -47, 94, -6, 100, -53, -76, -105, -66, 43, -68, 119, 46, 3, -45, 25, 89, -63, 29, 6, 65, 107, 85, -16, -103, 105, -22, -100, 24, -82, 99, -33, -25, -69, 0, 115, 102, -5, -106, 76, -123, -28, 58, 9, 69, -86, 15, -18, 16, -21, 45, 127, -12, 41, -84, -49, -83, -111, -115, 120, -56, -107, -7, 47, -50, -51, 8, 122, -120, 56, 92, -125, 42, 40, 71, -37, -72, -57, -109, -92, 18, 83, -1, -121, 14, 49, 54, 33, 88, 72, 1, -114, 55, 116, 50, -54, -23, -79, -73, -85, 12, -41, -60, 86, 66, 38, 7, -104, 96, -39, -74, -71, 17, 64, -20, 32, -116, -67, -96, -55, -124, 4, 73, 35, -15, 79, 80, 31, 19, -36, -40, -64, -98, 87, -29, -61, 123, 101, 59, 2, -113, 62, -24, 37, -110, -27, 21, -35, -3, 23, -87, -65, -44, -102, 126, -59, 57, 103, -2, 118, -99, 67, -89, -31, -48, -11, 104, -14, 27, 52, 112, 5, -93, -118, -43, 121, -122, -88, 48, -58, 81, 75, 30, -90, 39, -10, 53, -46, 110, 36, 22, -126, 95, -38, -26, 117, -94, -17, 44, -78, 28, -97, 93, 111, -128, 10, 114, 68, -101, 108, -112, 11, 91, 51, 125, 90, 82, -13, 97, -95, -9, -80, -42, 63, 124, 109, -19, 20, -32, -91, 61, 34, -77, -8, -119, -34, 113, 26, -81, -70, -75, -127 };
        SB3_sbox = new byte[] { 82, 9, 106, -43, 48, 54, -91, 56, -65, 64, -93, -98, -127, -13, -41, -5, 124, -29, 57, -126, -101, 47, -1, -121, 52, -114, 67, 68, -60, -34, -23, -53, 84, 123, -108, 50, -90, -62, 35, 61, -18, 76, -107, 11, 66, -6, -61, 78, 8, 46, -95, 102, 40, -39, 36, -78, 118, 91, -94, 73, 109, -117, -47, 37, 114, -8, -10, 100, -122, 104, -104, 22, -44, -92, 92, -52, 93, 101, -74, -110, 108, 112, 72, 80, -3, -19, -71, -38, 94, 21, 70, 87, -89, -115, -99, -124, -112, -40, -85, 0, -116, -68, -45, 10, -9, -28, 88, 5, -72, -77, 69, 6, -48, 44, 30, -113, -54, 63, 15, 2, -63, -81, -67, 3, 1, 19, -118, 107, 58, -111, 17, 65, 79, 103, -36, -22, -105, -14, -49, -50, -16, -76, -26, 115, -106, -84, 116, 34, -25, -83, 53, -123, -30, -7, 55, -24, 28, 117, -33, 110, 71, -15, 26, 113, 29, 41, -59, -119, 111, -73, 98, 14, -86, 24, -66, 27, -4, 86, 62, 75, -58, -46, 121, 32, -102, -37, -64, -2, 120, -51, 90, -12, 31, -35, -88, 51, -120, 7, -57, 49, -79, 18, 16, 89, 39, -128, -20, 95, 96, 81, 127, -87, 25, -75, 74, 13, 45, -27, 122, -97, -109, -55, -100, -17, -96, -32, 59, 77, -82, 42, -11, -80, -56, -21, -69, 60, -125, 83, -103, 97, 23, 43, 4, 126, -70, 119, -42, 38, -31, 105, 20, 99, 85, 33, 12, 125 };
        SB4_sbox = new byte[] { 48, 104, -103, 27, -121, -71, 33, 120, 80, 57, -37, -31, 114, 9, 98, 60, 62, 126, 94, -114, -15, -96, -52, -93, 42, 29, -5, -74, -42, 32, -60, -115, -127, 101, -11, -119, -53, -99, 119, -58, 87, 67, 86, 23, -44, 64, 26, 77, -64, 99, 108, -29, -73, -56, 100, 106, 83, -86, 56, -104, 12, -12, -101, -19, 127, 34, 118, -81, -35, 58, 11, 88, 103, -120, 6, -61, 53, 13, 1, -117, -116, -62, -26, 95, 2, 36, 117, -109, 102, 30, -27, -30, 84, -40, 16, -50, 122, -24, 8, 44, 18, -105, 50, -85, -76, 39, 10, 35, -33, -17, -54, -39, -72, -6, -36, 49, 107, -47, -83, 25, 73, -67, 81, -106, -18, -28, -88, 65, -38, -1, -51, 85, -122, 54, -66, 97, 82, -8, -69, 14, -126, 72, 105, -102, -32, 71, -98, 92, 4, 75, 52, 21, 121, 38, -89, -34, 41, -82, -110, -41, -124, -23, -46, -70, 93, -13, -59, -80, -65, -92, 59, 113, 68, 70, 43, -4, -21, 111, -43, -10, 20, -2, 124, 112, 90, 125, -3, 47, 24, -125, 22, -91, -111, 31, 5, -107, 116, -87, -63, 91, 74, -123, 109, 19, 7, 79, 78, 69, -78, 15, -55, 28, -90, -68, -20, 115, -112, 123, -49, 89, -113, -95, -7, 45, -14, -79, 0, -108, 55, -97, -48, 46, -100, 110, 40, 63, -128, -16, 61, -45, 37, -118, -75, -25, 66, -77, -57, -22, -9, 76, 17, 51, 3, -94, -84, 96 };
    }
}
