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

package org.bouncycastle.crypto.engines;

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

public class XoodyakEngine extends AEADBaseEngine
{
    private final byte[] state;
    private int phase;
    private int mode;
    private static final int f_bPrime_1 = 47;
    private byte[] K;
    private byte[] iv;
    private static final int PhaseUp = 2;
    private static final int PhaseDown = 1;
    private static final int[] RC;
    private boolean encrypted;
    private byte aadcd;
    private static final int ModeKeyed = 0;
    private static final int ModeHash = 1;
    
    public XoodyakEngine() {
        this.algorithmName = "Xoodyak AEAD";
        final int key_SIZE = 16;
        this.MAC_SIZE = key_SIZE;
        this.IV_SIZE = key_SIZE;
        this.KEY_SIZE = key_SIZE;
        this.BlockSize = 24;
        this.AADBufferSize = 44;
        this.state = new byte[48];
        this.setInnerMembers(ProcessingBufferType.Immediate, AADOperatorType.Default, DataOperatorType.Counter);
    }
    
    @Override
    protected void init(final byte[] k, final byte[] iv) throws IllegalArgumentException {
        this.K = k;
        this.iv = iv;
    }
    
    @Override
    protected void processBufferAAD(final byte[] array, final int n) {
        this.AbsorbAny(array, n, this.AADBufferSize, this.aadcd);
        this.aadcd = 0;
    }
    
    @Override
    protected void processFinalAAD() {
        this.AbsorbAny(this.m_aad, 0, this.m_aadPos, this.aadcd);
    }
    
    @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) {
        up(this.mode, this.state, this.encrypted ? 0 : 128);
        Bytes.xor(this.BlockSize, this.state, array, n, array2, n2);
        down(this.mode, this.state, array, n, this.BlockSize, 0);
        this.phase = 1;
        this.encrypted = true;
    }
    
    @Override
    protected void processBufferDecrypt(final byte[] array, final int n, final byte[] array2, final int n2) {
        up(this.mode, this.state, this.encrypted ? 0 : 128);
        Bytes.xor(this.BlockSize, this.state, array, n, array2, n2);
        down(this.mode, this.state, array2, n2, this.BlockSize, 0);
        this.phase = 1;
        this.encrypted = true;
    }
    
    @Override
    protected void processFinalBlock(final byte[] array, final int n) {
        if (this.m_bufPos != 0 || !this.encrypted) {
            up(this.mode, this.state, this.encrypted ? 0 : 128);
            Bytes.xor(this.m_bufPos, this.state, this.m_buf, 0, array, n);
            if (this.forEncryption) {
                down(this.mode, this.state, this.m_buf, 0, this.m_bufPos, 0);
            }
            else {
                down(this.mode, this.state, array, n, this.m_bufPos, 0);
            }
            this.phase = 1;
        }
        up(this.mode, this.state, 64);
        System.arraycopy(this.state, 0, this.mac, 0, this.MAC_SIZE);
        this.phase = 2;
    }
    
    @Override
    protected void reset(final boolean b) {
        super.reset(b);
        Arrays.fill(this.state, (byte)0);
        this.encrypted = false;
        this.phase = 2;
        this.aadcd = 3;
        final int length = this.K.length;
        final int length2 = this.iv.length;
        final byte[] array = new byte[this.AADBufferSize];
        this.mode = 0;
        System.arraycopy(this.K, 0, array, 0, length);
        System.arraycopy(this.iv, 0, array, length, length2);
        array[length + length2] = (byte)length2;
        this.AbsorbAny(array, 0, length + length2 + 1, 2);
    }
    
    private void AbsorbAny(final byte[] array, int n, int i, int n2) {
        if (this.phase != 2) {
            up(this.mode, this.state, 0);
        }
        do {
            final int min = Math.min(i, this.AADBufferSize);
            down(this.mode, this.state, array, n, min, n2);
            this.phase = 1;
            n2 = 0;
            n += min;
            i -= min;
        } while (i != 0);
    }
    
    public static void up(final XoodyakDigest.Friend friend, final int n, final byte[] array, final int n2) {
        if (null == friend) {
            throw new NullPointerException("This method is only for use by XoodyakDigest");
        }
        up(n, array, n2);
    }
    
    private static void up(final int n, final byte[] array, final int n2) {
        if (n != 1) {
            final int n3 = 47;
            array[n3] ^= (byte)n2;
        }
        int littleEndianToInt = Pack.littleEndianToInt(array, 0);
        int littleEndianToInt2 = Pack.littleEndianToInt(array, 4);
        int littleEndianToInt3 = Pack.littleEndianToInt(array, 8);
        int littleEndianToInt4 = Pack.littleEndianToInt(array, 12);
        int n4 = Pack.littleEndianToInt(array, 16);
        int n5 = Pack.littleEndianToInt(array, 20);
        int n6 = Pack.littleEndianToInt(array, 24);
        int n7 = Pack.littleEndianToInt(array, 28);
        int n8 = Pack.littleEndianToInt(array, 32);
        int n9 = Pack.littleEndianToInt(array, 36);
        int n10 = Pack.littleEndianToInt(array, 40);
        int n11 = Pack.littleEndianToInt(array, 44);
        for (int i = 0; i < 12; ++i) {
            final int n12 = littleEndianToInt ^ n4 ^ n8;
            final int n13 = littleEndianToInt2 ^ n5 ^ n9;
            final int n14 = littleEndianToInt3 ^ n6 ^ n10;
            final int n15 = littleEndianToInt4 ^ n7 ^ n11;
            final int n16 = Integers.rotateLeft(n15, 5) ^ Integers.rotateLeft(n15, 14);
            final int n17 = Integers.rotateLeft(n12, 5) ^ Integers.rotateLeft(n12, 14);
            final int n18 = Integers.rotateLeft(n13, 5) ^ Integers.rotateLeft(n13, 14);
            final int n19 = Integers.rotateLeft(n14, 5) ^ Integers.rotateLeft(n14, 14);
            final int n20 = littleEndianToInt ^ n16;
            final int n21 = n4 ^ n16;
            final int n22 = n8 ^ n16;
            final int n23 = littleEndianToInt2 ^ n17;
            final int n24 = n5 ^ n17;
            final int n25 = n9 ^ n17;
            final int n26 = littleEndianToInt3 ^ n18;
            final int n27 = n6 ^ n18;
            final int n28 = n10 ^ n18;
            final int n29 = littleEndianToInt4 ^ n19;
            final int n30 = n7 ^ n19;
            final int n31 = n11 ^ n19;
            final int n32 = n20;
            final int n33 = n23;
            final int n34 = n26;
            final int n35 = n29;
            final int n36 = n30;
            final int n37 = n21;
            final int n38 = n24;
            final int n39 = n27;
            final int rotateLeft = Integers.rotateLeft(n22, 11);
            final int rotateLeft2 = Integers.rotateLeft(n25, 11);
            final int rotateLeft3 = Integers.rotateLeft(n28, 11);
            final int rotateLeft4 = Integers.rotateLeft(n31, 11);
            final int n40 = n32 ^ XoodyakEngine.RC[i];
            littleEndianToInt = (n40 ^ (~n36 & rotateLeft));
            littleEndianToInt2 = (n33 ^ (~n37 & rotateLeft2));
            littleEndianToInt3 = (n34 ^ (~n38 & rotateLeft3));
            littleEndianToInt4 = (n35 ^ (~n39 & rotateLeft4));
            final int n41 = n36 ^ (~rotateLeft & n40);
            final int n42 = n37 ^ (~rotateLeft2 & n33);
            final int n43 = n38 ^ (~rotateLeft3 & n34);
            final int n44 = n39 ^ (~rotateLeft4 & n35);
            final int n45 = rotateLeft ^ (~n40 & n36);
            final int n46 = rotateLeft2 ^ (~n33 & n37);
            final int n47 = rotateLeft3 ^ (~n34 & n38);
            final int n48 = rotateLeft4 ^ (~n35 & n39);
            n4 = Integers.rotateLeft(n41, 1);
            n5 = Integers.rotateLeft(n42, 1);
            n6 = Integers.rotateLeft(n43, 1);
            n7 = Integers.rotateLeft(n44, 1);
            n8 = Integers.rotateLeft(n47, 8);
            n9 = Integers.rotateLeft(n48, 8);
            n10 = Integers.rotateLeft(n45, 8);
            n11 = Integers.rotateLeft(n46, 8);
        }
        Pack.intToLittleEndian(littleEndianToInt, array, 0);
        Pack.intToLittleEndian(littleEndianToInt2, array, 4);
        Pack.intToLittleEndian(littleEndianToInt3, array, 8);
        Pack.intToLittleEndian(littleEndianToInt4, array, 12);
        Pack.intToLittleEndian(n4, array, 16);
        Pack.intToLittleEndian(n5, array, 20);
        Pack.intToLittleEndian(n6, array, 24);
        Pack.intToLittleEndian(n7, array, 28);
        Pack.intToLittleEndian(n8, array, 32);
        Pack.intToLittleEndian(n9, array, 36);
        Pack.intToLittleEndian(n10, array, 40);
        Pack.intToLittleEndian(n11, array, 44);
    }
    
    public static void down(final XoodyakDigest.Friend friend, final int n, final byte[] array, final byte[] array2, final int n2, final int n3, final int n4) {
        if (null == friend) {
            throw new NullPointerException("This method is only for use by XoodyakDigest");
        }
        down(n, array, array2, n2, n3, n4);
    }
    
    private static void down(final int n, final byte[] array, final byte[] array2, final int n2, final int n3, final int n4) {
        Bytes.xorTo(n3, array2, n2, array);
        array[n3] ^= 0x1;
        final int n5 = 47;
        array[n5] ^= (byte)((n == 1) ? (n4 & 0x1) : n4);
    }
    
    static {
        RC = new int[] { 88, 56, 960, 208, 288, 20, 96, 44, 896, 240, 416, 18 };
    }
}
