Skip to content

Latest commit

 

History

History
151 lines (121 loc) · 7.38 KB

aesgcm.md

File metadata and controls

151 lines (121 loc) · 7.38 KB

AES-GCM

This encryption mode is described in [AES-GCM].

Nonce reuse

One of the undesirable properties of AES-GCM is that reusing the same IV for the same key leaks the authentication key [Joux-Gcm]. Typically, implementations can't enforce that users don't repeat IVs unless they use restricted interfaces. However, implementations should at least avoid features that increase the probability of incorrect usages.

One such dangerors featur in JCA is that the default behaviour of Cipher.doFinal is to reinitialize the cipher with the same parameters as the last encryption. For AES-GCM this behaviour would imply that the authencation key is leaked. Therefore, any reasonable implementation of AES-GCM should not allow two encryptions without an explicit initialization of the IV.

The expected behaviour of OpenJDK can be derived from the tests in jdk/test/com/sun/crypto/provider/Cipher/AES/TestGCMKeyAndIvCheck.java: OpenJDK does not allow two consecutive initializations for encryption with the same key and IV.

CTR overflow with IVs of size 12

The counter value in AES-GCM wraps around after $$2^{32}$$ blocks. If a plaintext is $$2^{32}$$ blocks or longer then the encryption would encrypt the same counter value twice, once to encrypt a block of plaintext and once to to compute the authentication tag. To avoid this implementations must not allow to encrypt plaintexts longer than $$2^{32}-2$$ blocks.

CTR overflow with IVs of sizes other than 12

What is the problem?

Incrementing counters in AES-GCM is different than incrementing counters in AES-CTR. AES-GCM increments counters modulo $$2^{32}$$, while AES-CTR increments them modulo $$2^{128}$$. E.g. if the counter value for a block is

0xffffffffffffffffffffffffffffffff

then the counter for the next block in AES-GCM is

0xffffffffffffffffffffffff00000000

But for AES-CTR the counter for the next block is

0x00000000000000000000000000000000

For AES-GCM the typical IV size is 12 bytes. For this size of the IV the counter starts as IV || 00000001. AES-GCM allows no ciphertexts longer than $$2^{32}-2$$ blocks. Hence for 12 byte IVs no counter overflow happens and it does not matter which version is used for incrementing counters. If the IV size is different than 12 bytes then initial IV is computed by using GHASH. The initial value can be any arbitrary 128-bit value and counter overflows are possible for messages longer than 16 bytes.

When an implementation of AES-GCM is handling CTR overflows incorrectly (e.g. reuses code from an AES-CTR implementation) then encrypting with an IV of size other than 12 bytes may result in incorrect ciphertext. This happens on average once every $$2^{32}$$ blocks of plaintext.

Encrypting with a faulty version of the code results in incorrect ciphertext, which can be decrypted again with the same faulty version of the code. When trying to decrypt with a correct version of AES-GCM then the authentication passes (since the authentication tag is computed over the ciphertext and thus unaffected by incorrect encryption), but the decrypted plaintext is incorrect. The situation where encryption is correct, but decryption is faulty is similar: the authentication passes, but the plaintext is wrong.

Besides returing incorrect plaintext, this bug can leak the authentication key. One scenario where this bug is exploitable is the following: We assume that there is a client-server scenario where either the client or the server use a faulty encryption rsp. decryption (but not both). We assume that the client sends AES-GCM encrypted messages of about 1 MB (i.e. $$2^{16}$$ blocks) to the server. (The size of the message is not very relevant. Fixing a size just makes the example a bit easier). We assume that random 16 byte IVs are used. (If the IVs are 12 bytes then faults don't happens. If the IVs are shorter or not random then the equations below may become dependent of each other. IVs longer than 16 bytes would complicate the equations.) We assume further that the attacker learns the ciphertext and that the attacker learns whether the ciphertext was corrupt or not. Under the assumptions above one out of every $$2^{16}$$ messages is encrypted or decrypted incorrectly. The attacker waits until he has 8 or 9 rejected messages. An incorrect decryption indicates that a counter overflow occurred, and hence that the initial counter was 0x????????????????????ffff????, where ? or unknown nibbles. The initial counter J0 is computed over $$\mbox{GF}(2^{128})$$ as $$J_0 = \mbox{IV} * H^2 + \mbox{len}(\mbox{IV})\cdot H$$ where H is the authentication key. Hence, $$J_0$$ is a linear function of H over $$\mbox{GF}(2^{128})$$. Equivalently, the equation above is a system of 128 linear equations over $$\mbox{GF}(2)$$, i.e. one equation for each bit of $$J_0$$. Under the assumptions above 16 bits of J0 are known for each message that is rejected. Knowing 8 or 9 rejected messages give 128 or 144 linear equations over $$\mbox{GF}(2)$$ with the 128 bits of H as unknowns. Hence, we expect that the system is solvable with high probability.

If the size of the encrypted messages is smaller, then less corrupt messages are necessary but more encryptions are necessary until sufficiently many bugs occur. The attack is a bit simpler if an attacker also learns the approx. position where the decrypted plaintext starts to become incorrect. Overall, approx. 200-600 GB of data needs to be encrypted with the same key so that the attack here gets enough information to derive the authentication key.

The attack above is just one way to exploit the weakness. Other attack scenarios might be possible, but I haven't explored them. In particular the attack above is passive. The attacker just needs the ability to observe an encrypted connection. The tag size is irrelevant.

Under the assumption that chosen ciphertext attacks are possible it might be possible to combine the attack above with Fergusons attack https://csrc.nist.gov/csrc/media/projects/block-cipher-techniques/documents/bcm/comments/cwc-gcm/ferguson2.pdf and attack connections with frequent key rotations.

Detecting the problem

Since GHASH is linear function it easy to construct test vectors where the counter overflow occurs within the first few increments. (I.e. one fixes $$J_0$$ and solves for a corresponding value for the IV.) An example for such a test case is:

key : "00112233445566778899aabbccddeeff",
iv : "dd9d0b4a0c3d681524bffca31d907661",
aad : "",
msg : "00000000000000000000000000000000000000000000000000000000000000000000000000000000",
ct : "64b19314c31af45accdf7e3c4db79f0d948ca37a8e6649e88aeffb1c598f3607007702417ea0e0bc",
tag : "5281efc7f13ac8e14ccf5dca7bfbfdd1",

Failing providers

The AES-GCM implementation in jdk9 handled CTR overflows incorrectly [CVE-2018-2972].

0 size IV

AES-GCM allows IVs of bit length $$1 \ldots 2^{64}-1$$. (See [NIST-SP800-38d], Section 5.2.1.1)

Disallowing IVs of length 0 is necessary. If an empty IV is used then the tag is an evaluation of a polynomial with the hash subkey as the value. Since the polynomial can be derived from the ciphertext it is known to an attacker. Therefore, any message encrypted with an empty IV leaks the hash subkey. In particular, encrypting an empty plaintext with an empty IV results in a ciphertext having a tag that is equal to the hash subkey used in AES-GCM. I.e. both are the same as encrypting an all zero block.