Beispiel #1
0
  private void gCTRBlock(byte[] block, byte[] out, int outOff) {
    byte[] tmp = getNextCounterBlock();

    GCMUtil.xor(tmp, block);
    System.arraycopy(tmp, 0, out, outOff, BLOCK_SIZE);

    gHASHBlock(S, forEncryption ? tmp : block);

    totalLength += BLOCK_SIZE;
  }
Beispiel #2
0
  private void gCTRPartial(byte[] buf, int off, int len, byte[] out, int outOff) {
    byte[] tmp = getNextCounterBlock();

    GCMUtil.xor(tmp, buf, off, len);
    System.arraycopy(tmp, 0, out, outOff, len);

    gHASHPartial(S, forEncryption ? tmp : buf, 0, len);

    totalLength += len;
  }
Beispiel #3
0
 private void gHASHPartial(byte[] Y, byte[] b, int off, int len) {
   GCMUtil.xor(Y, b, off, len);
   multiplier.multiplyH(Y);
 }
Beispiel #4
0
 private void gHASHBlock(byte[] Y, byte[] b) {
   GCMUtil.xor(Y, b);
   multiplier.multiplyH(Y);
 }
Beispiel #5
0
  @Override
  public int doFinal(byte[] out, int outOff)
      throws IllegalStateException, InvalidCipherTextException {
    if (totalLength == 0) {
      initCipher();
    }

    int extra = bufOff;

    if (forEncryption) {
      if (out.length < (outOff + extra + macSize)) {
        throw new OutputLengthException("Output buffer too short");
      }
    } else {
      if (extra < macSize) {
        throw new InvalidCipherTextException("data too short");
      }
      extra -= macSize;

      if (out.length < (outOff + extra)) {
        throw new OutputLengthException("Output buffer too short");
      }
    }

    if (extra > 0) {
      gCTRPartial(bufBlock, 0, extra, out, outOff);
    }

    atLength += atBlockPos;

    if (atLength > atLengthPre) {
      /*
       * Some AAD was sent after the cipher started. We determine the difference b/w the hash value
       * we actually used when the cipher started (S_atPre) and the final hash value calculated
       * (S_at). Then we carry this difference forward by multiplying by H^c, where c is the number
       * of (full or partial) cipher-text blocks produced, and adjust the current hash.
       */

      // Finish hash for partial AAD block
      if (atBlockPos > 0) {
        gHASHPartial(S_at, atBlock, 0, atBlockPos);
      }

      // Find the difference between the AAD hashes
      if (atLengthPre > 0) {
        GCMUtil.xor(S_at, S_atPre);
      }

      // Number of cipher-text blocks produced
      long c = ((totalLength * 8) + 127) >>> 7;

      // Calculate the adjustment factor
      byte[] H_c = new byte[16];
      if (exp == null) {
        exp = new Tables1kGCMExponentiator();
        exp.init(H);
      }
      exp.exponentiateX(c, H_c);

      // Carry the difference forward
      GCMUtil.multiply(S_at, H_c);

      // Adjust the current hash
      GCMUtil.xor(S, S_at);
    }

    // Final gHASH
    byte[] X = new byte[BLOCK_SIZE];
    Pack.longToBigEndian(atLength * 8, X, 0);
    Pack.longToBigEndian(totalLength * 8, X, 8);

    gHASHBlock(S, X);

    // T = MSBt(GCTRk(J0,S))
    byte[] tag = new byte[BLOCK_SIZE];
    cipher.processBlock(J0, 0, tag, 0);
    GCMUtil.xor(tag, S);

    int resultLen = extra;

    // We place into macBlock our calculated value for T
    this.macBlock = new byte[macSize];
    System.arraycopy(tag, 0, macBlock, 0, macSize);

    if (forEncryption) {
      // Append T to the message
      System.arraycopy(macBlock, 0, out, outOff + bufOff, macSize);
      resultLen += macSize;
    } else {
      // Retrieve the T value from the message and compare to calculated one
      byte[] msgMac = new byte[macSize];
      System.arraycopy(bufBlock, extra, msgMac, 0, macSize);
      if (!Arrays.constantTimeAreEqual(this.macBlock, msgMac)) {
        throw new InvalidCipherTextException("mac check in GCM failed");
      }
    }

    reset(false);

    return resultLen;
  }