use of com.google.security.wycheproof.WycheproofRunner.ExcludedTest in project wycheproof by google.
the class AesGcmTest method testWrappedAroundCounter.
/**
* Test AES-GCM wrapped around counter bug which leaks plaintext and authentication key. Let's
* consider 12-byte IV, counter = IV || 0^31 || 1. For each encryption block, the last 4 bytes of
* the counter is increased by 1. After 2^32 blocks, the counter will be wrapped around causing
* counter collision and hence, leaking plaintext and authentication key as explained below. The
* library must make a check to make sure that the plaintext's length never exceeds 2^32 - 2
* blocks. Note that this is different from usual IV collisions because it happens even if users
* use different IVs. <br>
* We have: <br>
* J0 = IV || 0^31 || 1 <br>
* Plaintext: P[0], P[1], P[2], .... <br>
* Ciphertext: <br>
* C[0] = Enc(K, (J0 + 1) % 2^32) XOR P[0] <br>
* C[1] = Enc(K, (J0 + 2) % 2^32) XOR P[1] <br>
* C[2] = Enc(K, (J0 + 3) % 2^32) XOR P[2] <br>
* ... <br>
* C[2^32 - 1] = Enc(K, J0) XOR P[2^32 - 1] <br>
* C[2^32] = Enc(K, (J0 + 1)% 2^32) XOR P[2^32] <br>
* It means that after 2^32 blocks, the counter is wrapped around causing counter collisions. In
* counter mode, once the counter is collided then it's reasonable to assume that the plaintext is
* leaked. As the ciphertext is already known to attacker, Enc(K, J0) is leaked. <br>
* Now, as the authentication tag T is computed as GHASH(H, {}, C) XOR E(K, J0), the attacker can
* learn GHASH(H, {}, C}. It essentially means that the attacker finds a polynomial where H is the
* root (see Joux attack http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/Joux_comments.pdf).
* Solving polynomial equation in GF(2^128) is enough to extract the authentication key.
*
* <p>BouncyCastle used to have this bug (CVE-2015-6644).
*
* <p>OpenJDK8 used to have this bug (http://hg.openjdk.java.net/jdk8u/jdk8u/jdk/rev/0c3ed12cdaf5)
*
* <p>The test is slow as we have to encrypt 2^32 blocks.
*/
@ExcludedTest(providers = { ProviderType.CONSCRYPT, ProviderType.BOUNCY_CASTLE, ProviderType.SPONGY_CASTLE }, comment = "Conscrypt doesn't support streaming, would crash. BouncyCastle needs > 1h.")
@SlowTest(providers = { ProviderType.BOUNCY_CASTLE, ProviderType.CONSCRYPT, ProviderType.OPENJDK, ProviderType.SPONGY_CASTLE })
@Test
public void testWrappedAroundCounter() throws Exception {
try {
byte[] iv = new byte[12];
byte[] input = new byte[16];
byte[] key = new byte[16];
(new SecureRandom()).nextBytes(key);
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "AES"), new GCMParameterSpec(16 * 8, iv));
byte[] output = cipher.update(input);
for (long i = 0; i < 4294967296L + 2; i++) {
byte[] output1 = cipher.update(input);
assertFalse("GCM Wrapped Around Counter" + i, Arrays.equals(output, output1));
}
fail("Expected Exception");
} catch (Exception expected) {
System.out.println("testWrappedAroundcounter:" + expected.toString());
}
}
Aggregations