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

package org.bouncycastle.crypto.engines;

import org.bouncycastle.util.Arrays;
import org.bouncycastle.util.Bytes;
import org.bouncycastle.util.Pack;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.DataLengthException;
import org.bouncycastle.crypto.InvalidCipherTextException;

public class ISAPEngine extends AEADBaseEngine
{
    private static final int ISAP_STATE_SZ = 40;
    private byte[] k;
    private byte[] npub;
    private int ISAP_rH;
    private final ISAP_AEAD ISAPAEAD;
    
    public ISAPEngine(final IsapType isapType) {
        final int key_SIZE = 16;
        this.MAC_SIZE = key_SIZE;
        this.IV_SIZE = key_SIZE;
        this.KEY_SIZE = key_SIZE;
        switch (isapType.ordinal()) {
            case 0: {
                this.ISAPAEAD = new ISAPAEAD_A_128A();
                this.algorithmName = "ISAP-A-128A AEAD";
                break;
            }
            case 1: {
                this.ISAPAEAD = new ISAPAEAD_K_128A();
                this.algorithmName = "ISAP-K-128A AEAD";
                break;
            }
            case 2: {
                this.ISAPAEAD = new ISAPAEAD_A_128();
                this.algorithmName = "ISAP-A-128 AEAD";
                break;
            }
            case 3: {
                this.ISAPAEAD = new ISAPAEAD_K_128();
                this.algorithmName = "ISAP-K-128 AEAD";
                break;
            }
            default: {
                throw new IllegalArgumentException("Incorrect ISAP parameter");
            }
        }
        this.AADBufferSize = this.BlockSize;
        this.setInnerMembers(ProcessingBufferType.Immediate, AADOperatorType.Default, DataOperatorType.Counter);
    }
    
    @Override
    protected void init(final byte[] k, final byte[] npub) throws IllegalArgumentException {
        this.npub = npub;
        this.k = k;
        this.ISAPAEAD.init();
    }
    
    @Override
    protected void processBufferAAD(final byte[] array, final int n) {
        this.ISAPAEAD.absorbMacBlock(array, n);
    }
    
    @Override
    protected void processFinalAAD() {
        this.ISAPAEAD.absorbFinalAADBlock();
    }
    
    @Override
    protected void finishAAD(final State state, final boolean b) {
        this.finishAAD3(state, b);
    }
    
    @Override
    protected void processBufferEncrypt(final byte[] array, final int n, final byte[] array2, final int n2) {
        this.ISAPAEAD.processEncBlock(array, n, array2, n2);
        this.ISAPAEAD.absorbMacBlock(array2, n2);
    }
    
    @Override
    protected void processBufferDecrypt(final byte[] array, final int n, final byte[] array2, final int n2) {
        this.ISAPAEAD.processEncBlock(array, n, array2, n2);
        this.ISAPAEAD.absorbMacBlock(array, n);
    }
    
    @Override
    protected void processFinalBlock(final byte[] array, final int n) {
        this.ISAPAEAD.processEncFinalBlock(array, n);
        if (this.forEncryption) {
            this.ISAPAEAD.processMACFinal(array, n, this.m_bufPos, this.mac);
        }
        else {
            this.ISAPAEAD.processMACFinal(this.m_buf, 0, this.m_bufPos, this.mac);
        }
    }
    
    @Override
    protected void reset(final boolean b) {
        super.reset(b);
        this.ISAPAEAD.reset();
    }
    
    private abstract class ISAPAEAD_A implements ISAP_AEAD
    {
        protected long[] k64;
        protected long[] npub64;
        protected long ISAP_IV1_64;
        protected long ISAP_IV2_64;
        protected long ISAP_IV3_64;
        AsconPermutationFriend.AsconPermutation p;
        AsconPermutationFriend.AsconPermutation mac;
        
        public ISAPAEAD_A() {
            ISAPEngine.this.ISAP_rH = 64;
            ISAPEngine.this.BlockSize = ISAPEngine.this.ISAP_rH + 7 >> 3;
            this.p = new AsconPermutationFriend.AsconPermutation();
            this.mac = new AsconPermutationFriend.AsconPermutation();
        }
        
        @Override
        public void init() {
            this.npub64 = new long[this.getLongSize(ISAPEngine.this.npub.length)];
            this.k64 = new long[this.getLongSize(ISAPEngine.this.k.length)];
            Pack.bigEndianToLong(ISAPEngine.this.npub, 0, this.npub64);
            Pack.bigEndianToLong(ISAPEngine.this.k, 0, this.k64);
        }
        
        protected abstract void PX1(final AsconPermutationFriend.AsconPermutation p0);
        
        protected abstract void PX2(final AsconPermutationFriend.AsconPermutation p0);
        
        @Override
        public void absorbMacBlock(final byte[] array, final int n) {
            final AsconPermutationFriend.AsconPermutation mac = this.mac;
            mac.x0 ^= Pack.bigEndianToLong(array, n);
            this.mac.p(12);
        }
        
        @Override
        public void absorbFinalAADBlock() {
            for (int i = 0; i < ISAPEngine.this.m_aadPos; ++i) {
                final AsconPermutationFriend.AsconPermutation mac = this.mac;
                mac.x0 ^= ((long)ISAPEngine.this.m_aad[i] & 0xFFL) << (7 - i << 3);
            }
            final AsconPermutationFriend.AsconPermutation mac2 = this.mac;
            mac2.x0 ^= 128L << (7 - ISAPEngine.this.m_aadPos << 3);
            this.mac.p(12);
            final AsconPermutationFriend.AsconPermutation mac3 = this.mac;
            mac3.x4 ^= 0x1L;
        }
        
        @Override
        public void processMACFinal(final byte[] array, int n, final int n2, final byte[] array2) {
            for (int i = 0; i < n2; ++i) {
                final AsconPermutationFriend.AsconPermutation mac = this.mac;
                mac.x0 ^= ((long)array[n++] & 0xFFL) << (7 - i << 3);
            }
            final AsconPermutationFriend.AsconPermutation mac2 = this.mac;
            mac2.x0 ^= 128L << (7 - n2 << 3);
            this.mac.p(12);
            Pack.longToBigEndian(this.mac.x0, array2, 0);
            Pack.longToBigEndian(this.mac.x1, array2, 8);
            final long x2 = this.mac.x2;
            final long x3 = this.mac.x3;
            final long x4 = this.mac.x4;
            this.isap_rk(this.mac, this.ISAP_IV2_64, array2, ISAPEngine.this.KEY_SIZE);
            this.mac.x2 = x2;
            this.mac.x3 = x3;
            this.mac.x4 = x4;
            this.mac.p(12);
            Pack.longToBigEndian(this.mac.x0, array2, 0);
            Pack.longToBigEndian(this.mac.x1, array2, 8);
        }
        
        private void isap_rk(final AsconPermutationFriend.AsconPermutation asconPermutation, final long n, final byte[] array, final int n2) {
            asconPermutation.set(this.k64[0], this.k64[1], n, 0L, 0L);
            asconPermutation.p(12);
            for (int i = 0; i < (n2 << 3) - 1; ++i) {
                asconPermutation.x0 ^= ((long)((array[i >>> 3] >>> 7 - (i & 0x7) & 0x1) << 7) & 0xFFL) << 56;
                this.PX2(asconPermutation);
            }
            asconPermutation.x0 ^= ((long)array[n2 - 1] & 0x1L) << 7 << 56;
            asconPermutation.p(12);
        }
        
        @Override
        public void processEncBlock(final byte[] array, final int n, final byte[] array2, final int n2) {
            Pack.longToBigEndian(Pack.bigEndianToLong(array, n) ^ this.p.x0, array2, n2);
            this.PX1(this.p);
        }
        
        @Override
        public void processEncFinalBlock(final byte[] array, final int n) {
            Bytes.xor(ISAPEngine.this.m_bufPos, Pack.longToLittleEndian(this.p.x0), ISAPEngine.this.BlockSize - ISAPEngine.this.m_bufPos, ISAPEngine.this.m_buf, 0, array, n);
        }
        
        @Override
        public void reset() {
            this.isap_rk(this.p, this.ISAP_IV3_64, ISAPEngine.this.npub, ISAPEngine.this.IV_SIZE);
            this.p.x3 = this.npub64[0];
            this.p.x4 = this.npub64[1];
            this.PX1(this.p);
            this.mac.set(this.npub64[0], this.npub64[1], this.ISAP_IV1_64, 0L, 0L);
            this.mac.p(12);
        }
        
        private int getLongSize(final int n) {
            return n + 7 >>> 3;
        }
    }
    
    private class ISAPAEAD_A_128 extends ISAPAEAD_A
    {
        public ISAPAEAD_A_128() {
            this.ISAP_IV1_64 = 108156764298152972L;
            this.ISAP_IV2_64 = 180214358336080908L;
            this.ISAP_IV3_64 = 252271952374008844L;
        }
        
        @Override
        protected void PX1(final AsconPermutationFriend.AsconPermutation asconPermutation) {
            asconPermutation.p(12);
        }
        
        @Override
        protected void PX2(final AsconPermutationFriend.AsconPermutation asconPermutation) {
            asconPermutation.p(12);
        }
    }
    
    private class ISAPAEAD_A_128A extends ISAPAEAD_A
    {
        public ISAPAEAD_A_128A() {
            this.ISAP_IV1_64 = 108156764297430540L;
            this.ISAP_IV2_64 = 180214358335358476L;
            this.ISAP_IV3_64 = 252271952373286412L;
        }
        
        @Override
        protected void PX1(final AsconPermutationFriend.AsconPermutation asconPermutation) {
            asconPermutation.p(6);
        }
        
        @Override
        protected void PX2(final AsconPermutationFriend.AsconPermutation asconPermutation) {
            asconPermutation.round(75L);
        }
    }
    
    private abstract class ISAPAEAD_K implements ISAP_AEAD
    {
        protected final int ISAP_STATE_SZ_CRYPTO_NPUBBYTES;
        protected short[] ISAP_IV1_16;
        protected short[] ISAP_IV2_16;
        protected short[] ISAP_IV3_16;
        protected short[] k16;
        protected short[] iv16;
        private final int[] KeccakF400RoundConstants;
        protected short[] SX;
        protected short[] macSX;
        protected short[] E;
        protected short[] C;
        protected short[] macE;
        protected short[] macC;
        
        public ISAPAEAD_K() {
            this.ISAP_STATE_SZ_CRYPTO_NPUBBYTES = 40 - ISAPEngine.this.IV_SIZE;
            this.KeccakF400RoundConstants = new int[] { 1, 32898, 32906, 32768, 32907, 1, 32897, 32777, 138, 136, 32777, 10, 32907, 139, 32905, 32771, 32770, 128, 32778, 10 };
            this.SX = new short[25];
            this.macSX = new short[25];
            this.E = new short[25];
            this.C = new short[5];
            this.macE = new short[25];
            this.macC = new short[5];
            ISAPEngine.this.ISAP_rH = 144;
            ISAPEngine.this.BlockSize = ISAPEngine.this.ISAP_rH + 7 >> 3;
        }
        
        @Override
        public void init() {
            this.k16 = new short[ISAPEngine.this.k.length >> 1];
            Pack.littleEndianToShort(ISAPEngine.this.k, 0, this.k16, 0, this.k16.length);
            this.iv16 = new short[ISAPEngine.this.npub.length >> 1];
            Pack.littleEndianToShort(ISAPEngine.this.npub, 0, this.iv16, 0, this.iv16.length);
        }
        
        @Override
        public void reset() {
            Arrays.fill(this.SX, (short)0);
            this.isap_rk(this.ISAP_IV3_16, ISAPEngine.this.npub, ISAPEngine.this.IV_SIZE, this.SX, this.ISAP_STATE_SZ_CRYPTO_NPUBBYTES, this.C);
            System.arraycopy(this.iv16, 0, this.SX, 17, 8);
            this.PermuteRoundsKX(this.SX, this.E, this.C);
            Arrays.fill(this.macSX, 12, 25, (short)0);
            System.arraycopy(this.iv16, 0, this.macSX, 0, 8);
            System.arraycopy(this.ISAP_IV1_16, 0, this.macSX, 8, 4);
            this.PermuteRoundsHX(this.macSX, this.macE, this.macC);
        }
        
        protected abstract void PermuteRoundsHX(final short[] p0, final short[] p1, final short[] p2);
        
        protected abstract void PermuteRoundsKX(final short[] p0, final short[] p1, final short[] p2);
        
        protected abstract void PermuteRoundsBX(final short[] p0, final short[] p1, final short[] p2);
        
        @Override
        public void absorbMacBlock(final byte[] array, final int n) {
            this.byteToShortXor(array, n, this.macSX, ISAPEngine.this.BlockSize >> 1);
            this.PermuteRoundsHX(this.macSX, this.macE, this.macC);
        }
        
        @Override
        public void absorbFinalAADBlock() {
            for (int i = 0; i < ISAPEngine.this.m_aadPos; ++i) {
                final short[] macSX = this.macSX;
                final int n = i >> 1;
                macSX[n] ^= (short)((ISAPEngine.this.m_aad[i] & 0xFF) << ((i & 0x1) << 3));
            }
            final short[] macSX2 = this.macSX;
            final int n2 = ISAPEngine.this.m_aadPos >> 1;
            macSX2[n2] ^= (short)(128 << ((ISAPEngine.this.m_aadPos & 0x1) << 3));
            this.PermuteRoundsHX(this.macSX, this.macE, this.macC);
            final short[] macSX3 = this.macSX;
            final int n3 = 24;
            macSX3[n3] ^= 0x100;
        }
        
        public void isap_rk(final short[] array, final byte[] array2, final int n, final short[] array3, final int n2, final short[] array4) {
            final short[] array5 = new short[25];
            final short[] array6 = new short[25];
            System.arraycopy(this.k16, 0, array5, 0, 8);
            System.arraycopy(array, 0, array5, 8, 4);
            this.PermuteRoundsKX(array5, array6, array4);
            for (int i = 0; i < (n << 3) - 1; ++i) {
                final short[] array7 = array5;
                final int n3 = 0;
                array7[n3] ^= (short)((array2[i >> 3] >>> 7 - (i & 0x7) & 0x1) << 7);
                this.PermuteRoundsBX(array5, array6, array4);
            }
            final short[] array8 = array5;
            final int n4 = 0;
            array8[n4] ^= (short)((array2[n - 1] & 0x1) << 7);
            this.PermuteRoundsKX(array5, array6, array4);
            System.arraycopy(array5, 0, array3, 0, (n2 == this.ISAP_STATE_SZ_CRYPTO_NPUBBYTES) ? 17 : 8);
        }
        
        @Override
        public void processMACFinal(final byte[] array, int n, final int n2, final byte[] array2) {
            for (int i = 0; i < n2; ++i) {
                final short[] macSX = this.macSX;
                final int n3 = i >> 1;
                macSX[n3] ^= (short)((array[n++] & 0xFF) << ((i & 0x1) << 3));
            }
            final short[] macSX2 = this.macSX;
            final int n4 = n2 >> 1;
            macSX2[n4] ^= (short)(128 << ((n2 & 0x1) << 3));
            this.PermuteRoundsHX(this.macSX, this.macE, this.macC);
            Pack.shortToLittleEndian(this.macSX, 0, 8, array2, 0);
            this.isap_rk(this.ISAP_IV2_16, array2, ISAPEngine.this.KEY_SIZE, this.macSX, ISAPEngine.this.KEY_SIZE, this.macC);
            this.PermuteRoundsHX(this.macSX, this.macE, this.macC);
            Pack.shortToLittleEndian(this.macSX, 0, 8, array2, 0);
        }
        
        @Override
        public void processEncBlock(final byte[] array, int n, final byte[] array2, int n2) {
            for (int i = 0; i < ISAPEngine.this.BlockSize; ++i) {
                array2[n2++] = (byte)(this.SX[i >> 1] >>> ((i & 0x1) << 3) ^ array[n++]);
            }
            this.PermuteRoundsKX(this.SX, this.E, this.C);
        }
        
        @Override
        public void processEncFinalBlock(final byte[] array, int n) {
            for (int i = 0; i < ISAPEngine.this.m_bufPos; ++i) {
                array[n++] = (byte)(this.SX[i >> 1] >>> ((i & 0x1) << 3) ^ ISAPEngine.this.m_buf[i]);
            }
        }
        
        private void byteToShortXor(final byte[] array, final int n, final short[] array2, final int n2) {
            for (int i = 0; i < n2; ++i) {
                final int n3 = i;
                array2[n3] ^= Pack.littleEndianToShort(array, n + (i << 1));
            }
        }
        
        protected void rounds12X(final short[] array, final short[] array2, final short[] array3) {
            this.prepareThetaX(array, array3);
            this.rounds_8_18(array, array2, array3);
        }
        
        protected void rounds_4_18(final short[] array, final short[] array2, final short[] array3) {
            this.thetaRhoPiChiIotaPrepareTheta(4, array, array2, array3);
            this.thetaRhoPiChiIotaPrepareTheta(5, array2, array, array3);
            this.thetaRhoPiChiIotaPrepareTheta(6, array, array2, array3);
            this.thetaRhoPiChiIotaPrepareTheta(7, array2, array, array3);
            this.rounds_8_18(array, array2, array3);
        }
        
        protected void rounds_8_18(final short[] array, final short[] array2, final short[] array3) {
            this.thetaRhoPiChiIotaPrepareTheta(8, array, array2, array3);
            this.thetaRhoPiChiIotaPrepareTheta(9, array2, array, array3);
            this.thetaRhoPiChiIotaPrepareTheta(10, array, array2, array3);
            this.thetaRhoPiChiIotaPrepareTheta(11, array2, array, array3);
            this.rounds_12_18(array, array2, array3);
        }
        
        protected void rounds_12_18(final short[] array, final short[] array2, final short[] array3) {
            this.thetaRhoPiChiIotaPrepareTheta(12, array, array2, array3);
            this.thetaRhoPiChiIotaPrepareTheta(13, array2, array, array3);
            this.thetaRhoPiChiIotaPrepareTheta(14, array, array2, array3);
            this.thetaRhoPiChiIotaPrepareTheta(15, array2, array, array3);
            this.thetaRhoPiChiIotaPrepareTheta(16, array, array2, array3);
            this.thetaRhoPiChiIotaPrepareTheta(17, array2, array, array3);
            this.thetaRhoPiChiIotaPrepareTheta(18, array, array2, array3);
            this.thetaRhoPiChiIota(array2, array, array3);
        }
        
        protected void prepareThetaX(final short[] array, final short[] array2) {
            array2[0] = (short)(array[0] ^ array[5] ^ array[10] ^ array[15] ^ array[20]);
            array2[1] = (short)(array[1] ^ array[6] ^ array[11] ^ array[16] ^ array[21]);
            array2[2] = (short)(array[2] ^ array[7] ^ array[12] ^ array[17] ^ array[22]);
            array2[3] = (short)(array[3] ^ array[8] ^ array[13] ^ array[18] ^ array[23]);
            array2[4] = (short)(array[4] ^ array[9] ^ array[14] ^ array[19] ^ array[24]);
        }
        
        private short ROL16(final short n, final int n2) {
            return (short)((n & 0xFFFF) << n2 ^ (n & 0xFFFF) >>> 16 - n2);
        }
        
        protected void thetaRhoPiChiIotaPrepareTheta(final int n, final short[] array, final short[] array2, final short[] array3) {
            final short n2 = (short)(array3[4] ^ this.ROL16(array3[1], 1));
            final short n3 = (short)(array3[0] ^ this.ROL16(array3[2], 1));
            final short n4 = (short)(array3[1] ^ this.ROL16(array3[3], 1));
            final short n5 = (short)(array3[2] ^ this.ROL16(array3[4], 1));
            final short n6 = (short)(array3[3] ^ this.ROL16(array3[0], 1));
            final int n7 = 0;
            final short n8 = (short)(array[n7] ^ n2);
            array[n7] = n8;
            final short n9 = n8;
            final int n10 = 6;
            array[n10] ^= n3;
            final short rol16 = this.ROL16(array[6], 12);
            final int n11 = 12;
            array[n11] ^= n4;
            final short rol17 = this.ROL16(array[12], 11);
            final int n12 = 18;
            array[n12] ^= n5;
            final short rol18 = this.ROL16(array[18], 5);
            final int n13 = 24;
            array[n13] ^= n6;
            final short rol19 = this.ROL16(array[24], 14);
            array3[0] = (array2[0] = (short)(n9 ^ (~rol16 & rol17) ^ this.KeccakF400RoundConstants[n]));
            array3[1] = (array2[1] = (short)(rol16 ^ (~rol17 & rol18)));
            array3[2] = (array2[2] = (short)(rol17 ^ (~rol18 & rol19)));
            array3[3] = (array2[3] = (short)(rol18 ^ (~rol19 & n9)));
            array3[4] = (array2[4] = (short)(rol19 ^ (~n9 & rol16)));
            final int n14 = 3;
            array[n14] ^= n5;
            final short rol20 = this.ROL16(array[3], 12);
            final int n15 = 9;
            array[n15] ^= n6;
            final short rol21 = this.ROL16(array[9], 4);
            final int n16 = 10;
            array[n16] ^= n2;
            final short rol22 = this.ROL16(array[10], 3);
            final int n17 = 16;
            array[n17] ^= n3;
            final short rol23 = this.ROL16(array[16], 13);
            final int n18 = 22;
            array[n18] ^= n4;
            final short rol24 = this.ROL16(array[22], 13);
            array2[5] = (short)(rol20 ^ (~rol21 & rol22));
            final int n19 = 0;
            array3[n19] ^= array2[5];
            array2[6] = (short)(rol21 ^ (~rol22 & rol23));
            final int n20 = 1;
            array3[n20] ^= array2[6];
            array2[7] = (short)(rol22 ^ (~rol23 & rol24));
            final int n21 = 2;
            array3[n21] ^= array2[7];
            array2[8] = (short)(rol23 ^ (~rol24 & rol20));
            final int n22 = 3;
            array3[n22] ^= array2[8];
            array2[9] = (short)(rol24 ^ (~rol20 & rol21));
            final int n23 = 4;
            array3[n23] ^= array2[9];
            final int n24 = 1;
            array[n24] ^= n3;
            final short rol25 = this.ROL16(array[1], 1);
            final int n25 = 7;
            array[n25] ^= n4;
            final short rol26 = this.ROL16(array[7], 6);
            final int n26 = 13;
            array[n26] ^= n5;
            final short rol27 = this.ROL16(array[13], 9);
            final int n27 = 19;
            array[n27] ^= n6;
            final short rol28 = this.ROL16(array[19], 8);
            final int n28 = 20;
            array[n28] ^= n2;
            final short rol29 = this.ROL16(array[20], 2);
            array2[10] = (short)(rol25 ^ (~rol26 & rol27));
            final int n29 = 0;
            array3[n29] ^= array2[10];
            array2[11] = (short)(rol26 ^ (~rol27 & rol28));
            final int n30 = 1;
            array3[n30] ^= array2[11];
            array2[12] = (short)(rol27 ^ (~rol28 & rol29));
            final int n31 = 2;
            array3[n31] ^= array2[12];
            array2[13] = (short)(rol28 ^ (~rol29 & rol25));
            final int n32 = 3;
            array3[n32] ^= array2[13];
            array2[14] = (short)(rol29 ^ (~rol25 & rol26));
            final int n33 = 4;
            array3[n33] ^= array2[14];
            final int n34 = 4;
            array[n34] ^= n6;
            final short rol30 = this.ROL16(array[4], 11);
            final int n35 = 5;
            array[n35] ^= n2;
            final short rol31 = this.ROL16(array[5], 4);
            final int n36 = 11;
            array[n36] ^= n3;
            final short rol32 = this.ROL16(array[11], 10);
            final int n37 = 17;
            array[n37] ^= n4;
            final short rol33 = this.ROL16(array[17], 15);
            final int n38 = 23;
            array[n38] ^= n5;
            final short rol34 = this.ROL16(array[23], 8);
            array2[15] = (short)(rol30 ^ (~rol31 & rol32));
            final int n39 = 0;
            array3[n39] ^= array2[15];
            array2[16] = (short)(rol31 ^ (~rol32 & rol33));
            final int n40 = 1;
            array3[n40] ^= array2[16];
            array2[17] = (short)(rol32 ^ (~rol33 & rol34));
            final int n41 = 2;
            array3[n41] ^= array2[17];
            array2[18] = (short)(rol33 ^ (~rol34 & rol30));
            final int n42 = 3;
            array3[n42] ^= array2[18];
            array2[19] = (short)(rol34 ^ (~rol30 & rol31));
            final int n43 = 4;
            array3[n43] ^= array2[19];
            final int n44 = 2;
            array[n44] ^= n4;
            final short rol35 = this.ROL16(array[2], 14);
            final int n45 = 8;
            array[n45] ^= n5;
            final short rol36 = this.ROL16(array[8], 7);
            final int n46 = 14;
            array[n46] ^= n6;
            final short rol37 = this.ROL16(array[14], 7);
            final int n47 = 15;
            array[n47] ^= n2;
            final short rol38 = this.ROL16(array[15], 9);
            final int n48 = 21;
            array[n48] ^= n3;
            final short rol39 = this.ROL16(array[21], 2);
            array2[20] = (short)(rol35 ^ (~rol36 & rol37));
            final int n49 = 0;
            array3[n49] ^= array2[20];
            array2[21] = (short)(rol36 ^ (~rol37 & rol38));
            final int n50 = 1;
            array3[n50] ^= array2[21];
            array2[22] = (short)(rol37 ^ (~rol38 & rol39));
            final int n51 = 2;
            array3[n51] ^= array2[22];
            array2[23] = (short)(rol38 ^ (~rol39 & rol35));
            final int n52 = 3;
            array3[n52] ^= array2[23];
            array2[24] = (short)(rol39 ^ (~rol35 & rol36));
            final int n53 = 4;
            array3[n53] ^= array2[24];
        }
        
        protected void thetaRhoPiChiIota(final short[] array, final short[] array2, final short[] array3) {
            final short n = (short)(array3[4] ^ this.ROL16(array3[1], 1));
            final short n2 = (short)(array3[0] ^ this.ROL16(array3[2], 1));
            final short n3 = (short)(array3[1] ^ this.ROL16(array3[3], 1));
            final short n4 = (short)(array3[2] ^ this.ROL16(array3[4], 1));
            final short n5 = (short)(array3[3] ^ this.ROL16(array3[0], 1));
            final int n6 = 0;
            final short n7 = (short)(array[n6] ^ n);
            array[n6] = n7;
            final short n8 = n7;
            final int n9 = 6;
            array[n9] ^= n2;
            final short rol16 = this.ROL16(array[6], 12);
            final int n10 = 12;
            array[n10] ^= n3;
            final short rol17 = this.ROL16(array[12], 11);
            final int n11 = 18;
            array[n11] ^= n4;
            final short rol18 = this.ROL16(array[18], 5);
            final int n12 = 24;
            array[n12] ^= n5;
            final short rol19 = this.ROL16(array[24], 14);
            array2[0] = (short)(n8 ^ (~rol16 & rol17) ^ this.KeccakF400RoundConstants[19]);
            array2[1] = (short)(rol16 ^ (~rol17 & rol18));
            array2[2] = (short)(rol17 ^ (~rol18 & rol19));
            array2[3] = (short)(rol18 ^ (~rol19 & n8));
            array2[4] = (short)(rol19 ^ (~n8 & rol16));
            final int n13 = 3;
            array[n13] ^= n4;
            final short rol20 = this.ROL16(array[3], 12);
            final int n14 = 9;
            array[n14] ^= n5;
            final short rol21 = this.ROL16(array[9], 4);
            final int n15 = 10;
            array[n15] ^= n;
            final short rol22 = this.ROL16(array[10], 3);
            final int n16 = 16;
            array[n16] ^= n2;
            final short rol23 = this.ROL16(array[16], 13);
            final int n17 = 22;
            array[n17] ^= n3;
            final short rol24 = this.ROL16(array[22], 13);
            array2[5] = (short)(rol20 ^ (~rol21 & rol22));
            array2[6] = (short)(rol21 ^ (~rol22 & rol23));
            array2[7] = (short)(rol22 ^ (~rol23 & rol24));
            array2[8] = (short)(rol23 ^ (~rol24 & rol20));
            array2[9] = (short)(rol24 ^ (~rol20 & rol21));
            final int n18 = 1;
            array[n18] ^= n2;
            final short rol25 = this.ROL16(array[1], 1);
            final int n19 = 7;
            array[n19] ^= n3;
            final short rol26 = this.ROL16(array[7], 6);
            final int n20 = 13;
            array[n20] ^= n4;
            final short rol27 = this.ROL16(array[13], 9);
            final int n21 = 19;
            array[n21] ^= n5;
            final short rol28 = this.ROL16(array[19], 8);
            final int n22 = 20;
            array[n22] ^= n;
            final short rol29 = this.ROL16(array[20], 2);
            array2[10] = (short)(rol25 ^ (~rol26 & rol27));
            array2[11] = (short)(rol26 ^ (~rol27 & rol28));
            array2[12] = (short)(rol27 ^ (~rol28 & rol29));
            array2[13] = (short)(rol28 ^ (~rol29 & rol25));
            array2[14] = (short)(rol29 ^ (~rol25 & rol26));
            final int n23 = 4;
            array[n23] ^= n5;
            final short rol30 = this.ROL16(array[4], 11);
            final int n24 = 5;
            array[n24] ^= n;
            final short rol31 = this.ROL16(array[5], 4);
            final int n25 = 11;
            array[n25] ^= n2;
            final short rol32 = this.ROL16(array[11], 10);
            final int n26 = 17;
            array[n26] ^= n3;
            final short rol33 = this.ROL16(array[17], 15);
            final int n27 = 23;
            array[n27] ^= n4;
            final short rol34 = this.ROL16(array[23], 8);
            array2[15] = (short)(rol30 ^ (~rol31 & rol32));
            array2[16] = (short)(rol31 ^ (~rol32 & rol33));
            array2[17] = (short)(rol32 ^ (~rol33 & rol34));
            array2[18] = (short)(rol33 ^ (~rol34 & rol30));
            array2[19] = (short)(rol34 ^ (~rol30 & rol31));
            final int n28 = 2;
            array[n28] ^= n3;
            final short rol35 = this.ROL16(array[2], 14);
            final int n29 = 8;
            array[n29] ^= n4;
            final short rol36 = this.ROL16(array[8], 7);
            final int n30 = 14;
            array[n30] ^= n5;
            final short rol37 = this.ROL16(array[14], 7);
            final int n31 = 15;
            array[n31] ^= n;
            final short rol38 = this.ROL16(array[15], 9);
            final int n32 = 21;
            array[n32] ^= n2;
            final short rol39 = this.ROL16(array[21], 2);
            array2[20] = (short)(rol35 ^ (~rol36 & rol37));
            array2[21] = (short)(rol36 ^ (~rol37 & rol38));
            array2[22] = (short)(rol37 ^ (~rol38 & rol39));
            array2[23] = (short)(rol38 ^ (~rol39 & rol35));
            array2[24] = (short)(rol39 ^ (~rol35 & rol36));
        }
    }
    
    private interface ISAP_AEAD
    {
        void init();
        
        void reset();
        
        void absorbMacBlock(final byte[] p0, final int p1);
        
        void absorbFinalAADBlock();
        
        void processEncBlock(final byte[] p0, final int p1, final byte[] p2, final int p3);
        
        void processEncFinalBlock(final byte[] p0, final int p1);
        
        void processMACFinal(final byte[] p0, final int p1, final int p2, final byte[] p3);
    }
    
    private class ISAPAEAD_K_128 extends ISAPAEAD_K
    {
        public ISAPAEAD_K_128() {
            this.ISAP_IV1_16 = new short[] { -32767, 400, 3092, 3084 };
            this.ISAP_IV2_16 = new short[] { -32766, 400, 3092, 3084 };
            this.ISAP_IV3_16 = new short[] { -32765, 400, 3092, 3084 };
        }
        
        @Override
        protected void PermuteRoundsHX(final short[] array, final short[] array2, final short[] array3) {
            this.prepareThetaX(array, array3);
            this.thetaRhoPiChiIotaPrepareTheta(0, array, array2, array3);
            this.thetaRhoPiChiIotaPrepareTheta(1, array2, array, array3);
            this.thetaRhoPiChiIotaPrepareTheta(2, array, array2, array3);
            this.thetaRhoPiChiIotaPrepareTheta(3, array2, array, array3);
            this.rounds_4_18(array, array2, array3);
        }
        
        @Override
        protected void PermuteRoundsKX(final short[] array, final short[] array2, final short[] array3) {
            this.rounds12X(array, array2, array3);
        }
        
        @Override
        protected void PermuteRoundsBX(final short[] array, final short[] array2, final short[] array3) {
            this.rounds12X(array, array2, array3);
        }
    }
    
    private class ISAPAEAD_K_128A extends ISAPAEAD_K
    {
        public ISAPAEAD_K_128A() {
            this.ISAP_IV1_16 = new short[] { -32767, 400, 272, 2056 };
            this.ISAP_IV2_16 = new short[] { -32766, 400, 272, 2056 };
            this.ISAP_IV3_16 = new short[] { -32765, 400, 272, 2056 };
        }
        
        @Override
        protected void PermuteRoundsHX(final short[] array, final short[] array2, final short[] array3) {
            this.prepareThetaX(array, array3);
            this.rounds_4_18(array, array2, array3);
        }
        
        @Override
        protected void PermuteRoundsKX(final short[] array, final short[] array2, final short[] array3) {
            this.prepareThetaX(array, array3);
            this.rounds_12_18(array, array2, array3);
        }
        
        @Override
        protected void PermuteRoundsBX(final short[] array, final short[] array2, final short[] array3) {
            this.prepareThetaX(array, array3);
            this.thetaRhoPiChiIotaPrepareTheta(19, array, array2, array3);
            System.arraycopy(array2, 0, array, 0, array2.length);
        }
    }
    
    public enum IsapType
    {
        ISAP_A_128A, 
        ISAP_K_128A, 
        ISAP_A_128, 
        ISAP_K_128;
    }
}
