public int processBlock(byte[] in, int inOff, byte[] out, int outOff)
      throws DataLengthException, IllegalStateException {
    cipher.processBlock(counter, 0, counterOut, 0);

    //
    // XOR the counterOut with the plaintext producing the cipher text
    //
    for (int i = 0; i < counterOut.length; i++) {
      out[outOff + i] = (byte) (counterOut[i] ^ in[inOff + i]);
    }

    int carry = 1;

    for (int i = counter.length - 1; i >= 0; i--) {
      int x = (counter[i] & 0xff) + carry;

      if (x > 0xff) {
        carry = 1;
      } else {
        carry = 0;
      }

      counter[i] = (byte) x;
    }

    return counter.length;
  }
 /**
  * Basic constructor.
  *
  * @param c the block cipher to be used.
  */
 public SICBlockCipher(BlockCipher c) {
   this.cipher = c;
   this.blockSize = cipher.getBlockSize();
   this.IV = new byte[blockSize];
   this.counter = new byte[blockSize];
   this.counterOut = new byte[blockSize];
 }
  public void init(
      boolean forEncryption, // ignored by this CTR mode
      CipherParameters params)
      throws IllegalArgumentException {
    if (params instanceof ParametersWithIV) {
      ParametersWithIV ivParam = (ParametersWithIV) params;
      byte[] iv = ivParam.getIV();
      System.arraycopy(iv, 0, IV, 0, IV.length);

      reset();
      cipher.init(true, ivParam.getParameters());
    } else {
      throw new IllegalArgumentException("SIC mode requires ParametersWithIV");
    }
  }
  /** Copy constructor. This will copy the state of the provided message digest. */
  public GOST3411Digest(GOST3411Digest t) {
    cipher.init(true, new ParametersWithSBox(null, GOST28147Engine.getSBox("D-A")));

    reset();

    System.arraycopy(t.H, 0, this.H, 0, t.H.length);
    System.arraycopy(t.L, 0, this.L, 0, t.L.length);
    System.arraycopy(t.M, 0, this.M, 0, t.M.length);
    System.arraycopy(t.Sum, 0, this.Sum, 0, t.Sum.length);
    System.arraycopy(t.C[1], 0, this.C[1], 0, t.C[1].length);
    System.arraycopy(t.C[2], 0, this.C[2], 0, t.C[2].length);
    System.arraycopy(t.C[3], 0, this.C[3], 0, t.C[3].length);
    System.arraycopy(t.xBuf, 0, this.xBuf, 0, t.xBuf.length);

    this.xBufOff = t.xBufOff;
    this.byteCount = t.byteCount;
  }
 public void reset() {
   System.arraycopy(IV, 0, counter, 0, counter.length);
   cipher.reset();
 }
 public int getBlockSize() {
   return cipher.getBlockSize();
 }
 public String getAlgorithmName() {
   return cipher.getAlgorithmName() + "/SIC";
 }
  /** Standard constructor */
  public GOST3411Digest() {
    cipher.init(true, new ParametersWithSBox(null, GOST28147Engine.getSBox("D-A")));

    reset();
  }
  // Encrypt function, ECB mode
  private void E(byte[] key, byte[] s, int sOff, byte[] in, int inOff) {
    cipher.init(true, new KeyParameter(key));

    cipher.processBlock(in, inOff, s, sOff);
  }