private int decryptBlock(
        byte[] in,
        int inOff,
        byte[] out,
        int outOff)
        throws DataLengthException, IllegalStateException
    {
        if ((inOff + blockSize) > in.length)
        {
            throw new DataLengthException("input buffer too short");
        }

        if ((outOff + blockSize) > out.length)
        {
            throw new DataLengthException("output buffer too short");
        }
        
        if (count > blockSize)
        {
            byte inVal = in[inOff];
            FR[blockSize - 2] = inVal;
            out[outOff] = encryptByte(inVal, blockSize - 2);

            inVal = in[inOff + 1];
            FR[blockSize - 1] = inVal;
            out[outOff + 1] = encryptByte(inVal, blockSize - 1);

            cipher.processBlock(FR, 0, FRE, 0);
            
            for (int n = 2; n < blockSize; n++) 
            {
                inVal = in[inOff + n];
                FR[n - 2] = inVal;
                out[outOff + n] = encryptByte(inVal, n - 2);
            }
        } 
        else if (count == 0)
        {
            cipher.processBlock(FR, 0, FRE, 0);
            
            for (int n = 0; n < blockSize; n++) 
            {
                FR[n] = in[inOff + n];
                out[n] = encryptByte(in[inOff + n], n);
            }
            
            count += blockSize;
        }
        else if (count == blockSize)
        {
            cipher.processBlock(FR, 0, FRE, 0);

            byte inVal1 = in[inOff];
            byte inVal2 = in[inOff + 1];
            out[outOff    ] = encryptByte(inVal1, 0);
            out[outOff + 1] = encryptByte(inVal2, 1);
            
            System.arraycopy(FR, 2, FR, 0, blockSize - 2);

            FR[blockSize - 2] = inVal1;
            FR[blockSize - 1] = inVal2;

            cipher.processBlock(FR, 0, FRE, 0);

            for (int n = 2; n < blockSize; n++) 
            {
                byte inVal = in[inOff + n];
                FR[n - 2] = inVal;
                out[outOff + n] = encryptByte(inVal, n - 2);
            }

            count += blockSize;
        }
        
        return blockSize;
    }