diff -r 54fb507a5d0c src/java.base/share/classes/com/sun/crypto/provider/CounterMode.java --- a/src/java.base/share/classes/com/sun/crypto/provider/CounterMode.java Sat Mar 25 01:43:49 2017 +0000 +++ b/src/java.base/share/classes/com/sun/crypto/provider/CounterMode.java Wed Mar 29 16:27:54 2017 -0400 @@ -45,7 +45,7 @@ final class CounterMode extends FeedbackCipher { // current counter value - private final byte[] counter; + private byte[] counter; // encrypted bytes of the previous counter value private final byte[] encryptedCounter; @@ -58,6 +58,14 @@ private byte[] encryptedCounterSave = null; private int usedSave = 0; + public byte[] getCounter() { + return counter; + } + + public void setCounter(byte[] counter) { + this.counter = counter; + } + CounterMode(SymmetricCipher embeddedCipher) { super(embeddedCipher); counter = new byte[blockSize]; @@ -130,6 +138,12 @@ embeddedCipher.init(false, algorithm, key); } + void init(byte[] iv) { + this.iv = iv; + + reset(); + } + /** * Performs encryption operation. * diff -r 54fb507a5d0c src/java.base/share/classes/com/sun/crypto/provider/GCTR.java --- a/src/java.base/share/classes/com/sun/crypto/provider/GCTR.java Sat Mar 25 01:43:49 2017 +0000 +++ b/src/java.base/share/classes/com/sun/crypto/provider/GCTR.java Wed Mar 29 16:27:54 2017 -0400 @@ -60,12 +60,11 @@ private final SymmetricCipher aes; private final byte[] icb; - // the current counter value - private byte[] counter; - // needed for save/restore calls private byte[] counterSave = null; + private CounterMode ctrMode; + // NOTE: cipher should already be initialized GCTR(SymmetricCipher cipher, byte[] initialCounterBlk) { this.aes = cipher; @@ -74,7 +73,9 @@ ") not equal to AES_BLOCK_SIZE (" + AES_BLOCK_SIZE + ")"); } this.icb = initialCounterBlk; - this.counter = icb.clone(); + + ctrMode = new CounterMode(cipher); + ctrMode.init(icb.clone()); } // input must be multiples of 128-bit blocks when calling update @@ -89,19 +90,8 @@ throw new RuntimeException("output buffer too small"); } - byte[] encryptedCntr = new byte[AES_BLOCK_SIZE]; + return ctrMode.encrypt(in, inOfs, inLen, out, outOfs); - int numOfCompleteBlocks = inLen / AES_BLOCK_SIZE; - for (int i = 0; i < numOfCompleteBlocks; i++) { - aes.encryptBlock(counter, 0, encryptedCntr, 0); - for (int n = 0; n < AES_BLOCK_SIZE; n++) { - int index = (i * AES_BLOCK_SIZE + n); - out[outOfs + index] = - (byte) ((in[inOfs + index] ^ encryptedCntr[n])); - } - GaloisCounterMode.increment32(counter); - } - return inLen; } // input can be arbitrary size when calling doFinal @@ -111,6 +101,8 @@ if (inLen < 0) { throw new IllegalBlockSizeException("Negative input size!"); } else if (inLen > 0) { + + int lastBlockSize = inLen % AES_BLOCK_SIZE; int completeBlkLen = inLen - lastBlockSize; // process the complete blocks first @@ -118,7 +110,7 @@ if (lastBlockSize != 0) { // do the last partial block byte[] encryptedCntr = new byte[AES_BLOCK_SIZE]; - aes.encryptBlock(counter, 0, encryptedCntr, 0); + aes.encryptBlock(ctrMode.getCounter(), 0, encryptedCntr, 0); for (int n = 0; n < lastBlockSize; n++) { out[outOfs + completeBlkLen + n] = (byte) ((in[inOfs + completeBlkLen + n] ^ @@ -136,7 +128,7 @@ * Resets the content of this object to when it's first constructed. */ void reset() { - System.arraycopy(icb, 0, counter, 0, icb.length); + System.arraycopy(icb, 0, ctrMode.getCounter(), 0, icb.length); counterSave = null; } @@ -144,7 +136,7 @@ * Save the current content of this object. */ void save() { - this.counterSave = this.counter.clone(); + this.counterSave = this.ctrMode.getCounter().clone(); } /** @@ -152,7 +144,7 @@ */ void restore() { if (this.counterSave != null) { - this.counter = this.counterSave; + this.ctrMode.setCounter(this.counterSave); } } }