I would like to understand the algebra behind GCM's security. Before I ask my questions, let me state my understanding of the math behind GCM. If correct, my questions are at the end; if incorrect, can you please explain my mistake.
For simplicity, assume only one block of ciphertext $c$. We want our tag to have two properties:
$tag_k(c)$ should be a universal uniform hash of $c$: that is, for all $c$, if $k$ is uniformly random, $P[tag_k(c) = y]$ is uniform for all $y$.
$tag_k(c)$ should reveal no information about $k$, even when $c$ is known.
Property 1 is easily satisfied by multiplication by non-zero $k$ in $GF(2^n)$, since, in $GF(2^n)$, $f(x) = ax$ is a unique permutation for all $a \ne 0$, and $f$ is therefore a universal uniform hash.
Property 2, however, would not be satisfied by $tag_k(c) = kc$, since we can compute $c{^-1}$ and solve $k = tag_k(c)c^{-1}$. To meet Property 2, we introduce a "secret ciphertext", $c_0$, and define $tag_k(c) = kc + c_0$ (addition being bitwise XOR in $GF(2^n)$). $c_0$ is effectively functioning as a one time pad to encrypt the "root" tag $kc$.
What if we want to authenticate two blocks of ciphertext? We could repeat that procedure, making sure to use a new $c_0$ each time. In practice, AES-GCM uses c_0 = AES_k(counter++)
.
However, when authenticating many blocks at once, this is inefficient. Instead, we can use one tag for multiple cipherblocks, using this formula:
$$tag_k(c_1, c_2,...c_n) = kc_0 + \sum k^nc_n.$$ (For simplicity, I am leaving out the length field as well as authenticated plaintext). This preserves both properties.
We might be tempted to simplify that to $\sum kc_n$, but this fails, as we can replace $c_a, c_b$ with $fake_a, fake_b$ as long as $fake_a + fake_b = c_a + c_b$. For example, we could flip a bit in any cipherblock as long as we flip the corresponding bit in a different block. (This type of attack was used against WEP, which uses CRC as its "MAC").
- Is the above correct?
- How does AES-GCM chose $k$?
More importantly, how do we avoid the following apparent failure modes:
- If $k = 0$, $tag(any\_ciphertext) = 0$
- Does $c_n = 0$ pose a problem? It doesn't seem to break any of the properties, but it still seems concerning. (Note that we can't simply append zero blocks, since this will change the length field.)
- It seems to me the multi-block algorithm would be correct if every $k$ was a generator of $GF(2^n)$ or at least of very high order. But if $k$ happens to be of low order, the scheme will fail.
For example: Imagine $k$ has order 2. Then we can flip a bit in $c_1$ as long as we flip the same bit in $c_3$, since $$\begin{align} k^2c_1 + k^4c_3 &= k^2(c_1 + c_3) \\ &= k^2(c_1 + c_3 + d + d) \\ &= k^2(c_1 + d) + k^4(c_3 + d)\end{align}.$$ How does GCM avoid this failure mode?