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

package org.bouncycastle.crypto.modes;

import org.bouncycastle.crypto.DataLengthException;
import org.bouncycastle.crypto.params.ParametersWithSBox;
import org.bouncycastle.crypto.params.ParametersWithRandom;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.BlockCipher;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.crypto.params.ParametersWithIV;
import org.bouncycastle.crypto.StreamBlockCipher;

public class GCFBBlockCipher extends StreamBlockCipher
{
    private static final byte[] C;
    private final CFBBlockCipher cfbEngine;
    private ParametersWithIV initParams;
    private KeyParameter key;
    private long counter;
    private boolean forEncryption;
    
    public GCFBBlockCipher(final BlockCipher blockCipher) {
        super(blockCipher);
        this.counter = 0L;
        this.cfbEngine = new CFBBlockCipher(blockCipher, blockCipher.getBlockSize() * 8);
    }
    
    @Override
    public void init(final boolean forEncryption, CipherParameters cipherParameters) throws IllegalArgumentException {
        this.counter = 0L;
        this.cfbEngine.init(forEncryption, cipherParameters);
        byte[] iv = null;
        this.forEncryption = forEncryption;
        if (cipherParameters instanceof ParametersWithIV) {
            final ParametersWithIV parametersWithIV = (ParametersWithIV)cipherParameters;
            cipherParameters = parametersWithIV.getParameters();
            iv = parametersWithIV.getIV();
        }
        if (cipherParameters instanceof ParametersWithRandom) {
            cipherParameters = ((ParametersWithRandom)cipherParameters).getParameters();
        }
        if (cipherParameters instanceof ParametersWithSBox) {
            cipherParameters = ((ParametersWithSBox)cipherParameters).getParameters();
        }
        this.key = (KeyParameter)cipherParameters;
        if (this.key == null && this.initParams != null) {
            this.key = (KeyParameter)this.initParams.getParameters();
        }
        byte[] array;
        if (iv == null && this.initParams != null) {
            array = this.initParams.getIV();
        }
        else {
            array = this.cfbEngine.getCurrentIV();
        }
        this.initParams = new ParametersWithIV(this.key, array);
    }
    
    @Override
    public String getAlgorithmName() {
        final String algorithmName = this.cfbEngine.getAlgorithmName();
        return algorithmName.substring(0, algorithmName.indexOf(47)) + "/G" + algorithmName.substring(algorithmName.indexOf(47) + 1);
    }
    
    @Override
    public int getBlockSize() {
        return this.cfbEngine.getBlockSize();
    }
    
    @Override
    public int processBlock(final byte[] array, final int n, final byte[] array2, final int n2) throws DataLengthException, IllegalStateException {
        this.processBytes(array, n, this.cfbEngine.getBlockSize(), array2, n2);
        return this.cfbEngine.getBlockSize();
    }
    
    @Override
    protected byte calculateByte(final byte b) {
        if (this.counter > 0L && (this.counter & 0x3FFL) == 0x0L) {
            final BlockCipher underlyingCipher = this.cfbEngine.getUnderlyingCipher();
            underlyingCipher.init(false, this.key);
            final byte[] array = new byte[32];
            for (int blockSize = underlyingCipher.getBlockSize(), i = 0; i < array.length; i += blockSize) {
                underlyingCipher.processBlock(GCFBBlockCipher.C, i, array, i);
            }
            underlyingCipher.init(true, this.key = new KeyParameter(array));
            final byte[] currentIV = this.cfbEngine.getCurrentIV();
            underlyingCipher.processBlock(currentIV, 0, currentIV, 0);
            this.cfbEngine.init(this.forEncryption, new ParametersWithIV(this.key, currentIV));
        }
        ++this.counter;
        return this.cfbEngine.calculateByte(b);
    }
    
    @Override
    public void reset() {
        this.counter = 0L;
        if (this.initParams != null) {
            this.key = (KeyParameter)this.initParams.getParameters();
            this.cfbEngine.init(this.forEncryption, this.initParams);
        }
        else {
            this.cfbEngine.reset();
        }
    }
    
    static {
        C = new byte[] { 105, 0, 114, 34, 100, -55, 4, 35, -115, 58, -37, -106, 70, -23, 42, -60, 24, -2, -84, -108, 0, -19, 7, 18, -64, -122, -36, -62, -17, 76, -87, 43 };
    }
}
