// 
// 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.crypto.digests.PhotonBeetleDigest;
import org.bouncycastle.util.Bytes;

public class PhotonBeetleEngine extends AEADBaseEngine
{
    private boolean input_empty;
    private byte[] K;
    private byte[] N;
    private byte[] state;
    private final int RATE_INBYTES_HALF;
    private final int STATE_INBYTES;
    private final int LAST_THREE_BITS_OFFSET;
    private static final int D = 8;
    private static final byte[][] RC;
    private static final byte[][] MixColMatrix;
    private static final byte[] sbox;
    
    public PhotonBeetleEngine(final PhotonBeetleParameters photonBeetleParameters) {
        final int key_SIZE = 16;
        this.MAC_SIZE = key_SIZE;
        this.IV_SIZE = key_SIZE;
        this.KEY_SIZE = key_SIZE;
        int n = 0;
        int n2 = 0;
        switch (photonBeetleParameters.ordinal()) {
            case 0: {
                n2 = 32;
                n = 224;
                break;
            }
            case 1: {
                n2 = 128;
                n = 128;
                break;
            }
        }
        final int n3 = n2 + 7 >>> 3;
        this.BlockSize = n3;
        this.AADBufferSize = n3;
        this.RATE_INBYTES_HALF = this.BlockSize >>> 1;
        final int n4 = n2 + n;
        this.STATE_INBYTES = n4 + 7 >>> 3;
        this.LAST_THREE_BITS_OFFSET = n4 - (this.STATE_INBYTES - 1 << 3) - 3;
        this.algorithmName = "Photon-Beetle AEAD";
        this.state = new byte[this.STATE_INBYTES];
        this.setInnerMembers(ProcessingBufferType.Buffered, AADOperatorType.Counter, DataOperatorType.Counter);
    }
    
    @Override
    protected void init(final byte[] k, final byte[] n) throws IllegalArgumentException {
        this.K = k;
        this.N = n;
    }
    
    @Override
    protected void processBufferAAD(final byte[] array, final int n) {
        photonPermutation(this.state);
        Bytes.xorTo(this.BlockSize, array, n, this.state);
    }
    
    @Override
    protected void finishAAD(final State state, final boolean b) {
        this.finishAAD3(state, b);
    }
    
    @Override
    protected void processFinalAAD() {
        final int len = this.aadOperator.getLen();
        if (len != 0) {
            if (this.m_aadPos != 0) {
                photonPermutation(this.state);
                Bytes.xorTo(this.m_aadPos, this.m_aad, this.state);
                if (this.m_aadPos < this.BlockSize) {
                    final byte[] state = this.state;
                    final int aadPos = this.m_aadPos;
                    state[aadPos] ^= 0x1;
                }
            }
            final byte[] state2 = this.state;
            final int n = this.STATE_INBYTES - 1;
            state2[n] ^= (byte)(this.select(this.dataOperator.getLen() - (this.forEncryption ? 0 : this.MAC_SIZE) > 0, len % this.BlockSize == 0, (byte)3, (byte)4) << this.LAST_THREE_BITS_OFFSET);
        }
    }
    
    @Override
    protected void processBufferEncrypt(final byte[] array, final int n, final byte[] array2, final int n2) {
        this.rhoohr(array2, n2, array, n, this.BlockSize);
        Bytes.xorTo(this.BlockSize, array, n, this.state);
    }
    
    @Override
    protected void processBufferDecrypt(final byte[] array, final int n, final byte[] array2, final int n2) {
        this.rhoohr(array2, n2, array, n, this.BlockSize);
        Bytes.xorTo(this.BlockSize, array2, n2, this.state);
    }
    
    @Override
    protected void processFinalBlock(final byte[] array, final int n) {
        final int n2 = this.dataOperator.getLen() - (this.forEncryption ? 0 : this.MAC_SIZE);
        final int bufPos = this.m_bufPos;
        final int len = this.aadOperator.getLen();
        if (len != 0 || n2 != 0) {
            this.input_empty = false;
        }
        final byte select = this.select(len != 0, n2 % this.BlockSize == 0, (byte)5, (byte)6);
        if (n2 != 0) {
            if (bufPos != 0) {
                this.rhoohr(array, n, this.m_buf, 0, bufPos);
                if (this.forEncryption) {
                    Bytes.xorTo(bufPos, this.m_buf, this.state);
                }
                else {
                    Bytes.xorTo(bufPos, array, n, this.state);
                }
                if (bufPos < this.BlockSize) {
                    final byte[] state = this.state;
                    final int n3 = bufPos;
                    state[n3] ^= 0x1;
                }
            }
            final byte[] state2 = this.state;
            final int n4 = this.STATE_INBYTES - 1;
            state2[n4] ^= (byte)(select << this.LAST_THREE_BITS_OFFSET);
        }
        else if (this.input_empty) {
            final byte[] state3 = this.state;
            final int n5 = this.STATE_INBYTES - 1;
            state3[n5] ^= (byte)(1 << this.LAST_THREE_BITS_OFFSET);
        }
        photonPermutation(this.state);
        System.arraycopy(this.state, 0, this.mac, 0, this.MAC_SIZE);
    }
    
    @Override
    protected void reset(final boolean b) {
        super.reset(b);
        this.input_empty = true;
        System.arraycopy(this.K, 0, this.state, 0, this.K.length);
        System.arraycopy(this.N, 0, this.state, this.K.length, this.N.length);
    }
    
    private static void photonPermutation(final byte[] array) {
        final int n = 3;
        final int n2 = 7;
        final int n3 = 64;
        final byte[][] array2 = new byte[8][8];
        for (int i = 0; i < n3; ++i) {
            array2[i >>> n][i & n2] = (byte)((array[i >> 1] & 0xFF) >>> 4 * (i & 0x1) & 0xF);
        }
        for (int n4 = 12, j = 0; j < n4; ++j) {
            for (int k = 0; k < 8; ++k) {
                final byte[] array3 = array2[k];
                final int n5 = 0;
                array3[n5] ^= PhotonBeetleEngine.RC[k][j];
            }
            for (int l = 0; l < 8; ++l) {
                for (int n6 = 0; n6 < 8; ++n6) {
                    array2[l][n6] = PhotonBeetleEngine.sbox[array2[l][n6]];
                }
            }
            for (int n7 = 1; n7 < 8; ++n7) {
                System.arraycopy(array2[n7], 0, array, 0, 8);
                System.arraycopy(array, n7, array2[n7], 0, 8 - n7);
                System.arraycopy(array, 0, array2[n7], 8 - n7, n7);
            }
            for (int n8 = 0; n8 < 8; ++n8) {
                for (int n9 = 0; n9 < 8; ++n9) {
                    int n10 = 0;
                    for (int n11 = 0; n11 < 8; ++n11) {
                        final byte b = PhotonBeetleEngine.MixColMatrix[n9][n11];
                        final byte b2 = array2[n11][n8];
                        n10 = (n10 ^ b * (b2 & 0x1) ^ b * (b2 & 0x2) ^ b * (b2 & 0x4) ^ b * (b2 & 0x8));
                    }
                    final int n12 = n10 >>> 4;
                    final int n13 = (n10 & 0xF) ^ n12 ^ n12 << 1;
                    final int n14 = n13 >>> 4;
                    array[n9] = (byte)((n13 & 0xF) ^ n14 ^ n14 << 1);
                }
                for (int n15 = 0; n15 < 8; ++n15) {
                    array2[n15][n8] = array[n15];
                }
            }
        }
        for (int n16 = 0; n16 < n3; n16 += 2) {
            array[n16 >>> 1] = (byte)((array2[n16 >>> n][n16 & n2] & 0xF) | (array2[n16 >>> n][n16 + 1 & n2] & 0xF) << 4);
        }
    }
    
    private byte select(final boolean b, final boolean b2, final byte b3, final byte b4) {
        if (b && b2) {
            return 1;
        }
        if (b) {
            return 2;
        }
        if (b2) {
            return b3;
        }
        return b4;
    }
    
    private void rhoohr(final byte[] array, final int n, final byte[] array2, final int n2, final int a) {
        photonPermutation(this.state);
        final byte[] array3 = new byte[8];
        final int min = Math.min(a, this.RATE_INBYTES_HALF);
        int i;
        for (i = 0; i < this.RATE_INBYTES_HALF - 1; ++i) {
            array3[i] = (byte)((this.state[i] & 0xFF) >>> 1 | (this.state[i + 1] & 0x1) << 7);
        }
        array3[this.RATE_INBYTES_HALF - 1] = (byte)((this.state[i] & 0xFF) >>> 1 | (this.state[0] & 0x1) << 7);
        Bytes.xor(min, this.state, this.RATE_INBYTES_HALF, array2, n2, array, n);
        Bytes.xor(a - min, array3, min - this.RATE_INBYTES_HALF, array2, n2 + min, array, n + min);
    }
    
    public static void photonPermutation(final PhotonBeetleDigest.Friend friend, final byte[] array) {
        if (null == friend) {
            throw new NullPointerException("This method is only for use by PhotonBeetleDigest");
        }
        photonPermutation(array);
    }
    
    static {
        RC = new byte[][] { { 1, 3, 7, 14, 13, 11, 6, 12, 9, 2, 5, 10 }, { 0, 2, 6, 15, 12, 10, 7, 13, 8, 3, 4, 11 }, { 2, 0, 4, 13, 14, 8, 5, 15, 10, 1, 6, 9 }, { 6, 4, 0, 9, 10, 12, 1, 11, 14, 5, 2, 13 }, { 14, 12, 8, 1, 2, 4, 9, 3, 6, 13, 10, 5 }, { 15, 13, 9, 0, 3, 5, 8, 2, 7, 12, 11, 4 }, { 13, 15, 11, 2, 1, 7, 10, 0, 5, 14, 9, 6 }, { 9, 11, 15, 6, 5, 3, 14, 4, 1, 10, 13, 2 } };
        MixColMatrix = new byte[][] { { 2, 4, 2, 11, 2, 8, 5, 6 }, { 12, 9, 8, 13, 7, 7, 5, 2 }, { 4, 4, 13, 13, 9, 4, 13, 9 }, { 1, 6, 5, 1, 12, 13, 15, 14 }, { 15, 12, 9, 13, 14, 5, 14, 13 }, { 9, 14, 5, 15, 4, 12, 9, 6 }, { 12, 2, 2, 10, 3, 1, 1, 14 }, { 15, 1, 13, 10, 5, 10, 2, 3 } };
        sbox = new byte[] { 12, 5, 6, 11, 9, 0, 10, 13, 3, 14, 15, 8, 4, 7, 1, 2 };
    }
    
    public enum PhotonBeetleParameters
    {
        pb32, 
        pb128;
    }
}
