diff --git a/src/main/java/com/southernstorm/noise/protocol/AESGCMFallbackCipherState.java b/src/main/java/com/southernstorm/noise/protocol/AESGCMFallbackCipherState.java index 74b3735..0add4c8 100644 --- a/src/main/java/com/southernstorm/noise/protocol/AESGCMFallbackCipherState.java +++ b/src/main/java/com/southernstorm/noise/protocol/AESGCMFallbackCipherState.java @@ -130,8 +130,7 @@ private void setup(byte[] ad) iv[13] = 0; iv[14] = 0; iv[15] = 1; - ++n; - + // Encrypt a block of zeroes to generate the hash key to XOR // the GHASH tag with at the end of the encrypt/decrypt operation. Arrays.fill(hashKey, (byte)0); @@ -207,6 +206,7 @@ public int encryptWithAd(byte[] ad, byte[] plaintext, int plaintextOffset, ghash.finish(ciphertext, ciphertextOffset + length, 16); for (int index = 0; index < 16; ++index) ciphertext[ciphertextOffset + length + index] ^= hashKey[index]; + n += 1; return length + 16; } @@ -247,6 +247,7 @@ public int decryptWithAd(byte[] ad, byte[] ciphertext, if ((temp & 0xFF) != 0) Noise.throwBadTagException(); encryptCTR(ciphertext, ciphertextOffset, plaintext, plaintextOffset, dataLen); + n += 1; return dataLen; } diff --git a/src/main/java/com/southernstorm/noise/protocol/AESGCMOnCtrCipherState.java b/src/main/java/com/southernstorm/noise/protocol/AESGCMOnCtrCipherState.java index 38c60d8..c4864fe 100644 --- a/src/main/java/com/southernstorm/noise/protocol/AESGCMOnCtrCipherState.java +++ b/src/main/java/com/southernstorm/noise/protocol/AESGCMOnCtrCipherState.java @@ -190,8 +190,7 @@ private void setup(byte[] ad) throws InvalidKeyException, InvalidAlgorithmParame iv[13] = 0; iv[14] = 0; iv[15] = 1; - ++n; - + // Initialize the CTR mode cipher with the key and IV. cipher.init(Cipher.ENCRYPT_MODE, keySpec, new IvParameterSpec(iv)); @@ -255,6 +254,7 @@ public int encryptWithAd(byte[] ad, byte[] plaintext, int plaintextOffset, ghash.finish(ciphertext, ciphertextOffset + length, 16); for (int index = 0; index < 16; ++index) ciphertext[ciphertextOffset + length + index] ^= hashKey[index]; + n += 1; return length + 16; } @@ -312,6 +312,7 @@ public int decryptWithAd(byte[] ad, byte[] ciphertext, // Shouldn't happen. throw new IllegalStateException(e); } + n += 1; return dataLen; } diff --git a/src/main/java/com/southernstorm/noise/protocol/ChaChaPolyCipherState.java b/src/main/java/com/southernstorm/noise/protocol/ChaChaPolyCipherState.java index 0e2ec93..78d7ac1 100644 --- a/src/main/java/com/southernstorm/noise/protocol/ChaChaPolyCipherState.java +++ b/src/main/java/com/southernstorm/noise/protocol/ChaChaPolyCipherState.java @@ -138,7 +138,7 @@ private void setup(byte[] ad) { if (n == -1L) throw new IllegalStateException("Nonce has wrapped around"); - ChaChaCore.initIV(input, n++); + ChaChaCore.initIV(input, n); ChaChaCore.hash(output, input); Arrays.fill(polyKey, (byte)0); xorBlock(polyKey, 0, polyKey, 0, 32, output); @@ -234,6 +234,7 @@ public int encryptWithAd(byte[] ad, byte[] plaintext, int plaintextOffset, poly.update(ciphertext, ciphertextOffset, length); finish(ad, length); System.arraycopy(polyKey, 0, ciphertext, ciphertextOffset + length, 16); + n += 1; return length + 16; } @@ -273,6 +274,7 @@ public int decryptWithAd(byte[] ad, byte[] ciphertext, if ((temp & 0xFF) != 0) Noise.throwBadTagException(); encrypt(ciphertext, ciphertextOffset, plaintext, plaintextOffset, dataLen); + n += 1; return dataLen; } diff --git a/src/test/java/com/southernstorm/noise/tests/CipherStateTests.java b/src/test/java/com/southernstorm/noise/tests/CipherStateTests.java index 239c891..f2aaafc 100644 --- a/src/test/java/com/southernstorm/noise/tests/CipherStateTests.java +++ b/src/test/java/com/southernstorm/noise/tests/CipherStateTests.java @@ -149,10 +149,11 @@ private void testCipher(String name, int keyLen, int macLen, fail(); } - // Fast-forward the nonce to just before the rollover. We will be able - // to decrypt one more block, and then the next request will be rejected. - cipher.setNonce(-2L); try { + // Fast-forward the nonce to just before the rollover. We will be able + // to decrypt one more block, and then the next request will be rejected. + cipher.setNonce(-2L); + buffer = new byte [plaintextBytes.length]; Arrays.fill(buffer, (byte)0xAA); try { @@ -161,6 +162,9 @@ private void testCipher(String name, int keyLen, int macLen, } catch (BadPaddingException e) { // Success! } + + cipher.setNonce(-1L); + try { cipher.decryptWithAd(adBytes, ciphertextBytes, 0, buffer, 0, ciphertextBytes.length); fail();