5
$\begingroup$

There is currently a GitHub discussion on .NET not supporting AES-GCM for any streaming data since releasing decrypted data prior to tag checks somehow reveals the plaintext or the AES key (or some such undocumented catastrophic failure). A lot of chatter between two choices:

1. Allowing AES-GCM for streaming data

Release data as it is decrypted and alert caller if / when tag check fails. Most popular AEAD constructs (e.g. AES-CBC-HMACSHA256) are encryption and authentication as two separate pipelines. So one can at least momentarily downgrade to privacy-only mode during decryption (i.e. AES-GCM => AES-CTR mode) but upgrade back to privacy and authentication mode after the GHASH tag checks out. The caller is responsible for alerting users or buffering data if situation demands.

2. Permanently disallow AES-GCM for all streaming data

This eliminates AEAD (or specifically AES-GCM) from streaming and limits them to regular privacy-only mode permanently. Or forces users to bolt-on authentication themselves, which revisits the original problem. Or worse, users consider streaming as a dead-end case and skip any encryption at all.

Question: Assuming everything else is ok (fresh keys, unique iv, long tags, under GCM limit etC), is allowing streaming (#1) with AES-GCM ok? If not, what's the catastrophic failure and what choice other than AEAD does streaming have? If the case for AES-GCM differs significantly from generalized AEAD, please address that too.

The Windows 'kernel' crypto layer (bcrypt), OpenSSL, Bouncy Castle (C#) and Java Cryptography Architecture all allow for streaming/continuation.

Also, the scope of this is the crypto API itself, NOT a high level protocol.

$\endgroup$
  • $\begingroup$ Most of the protocols are having fixed syntax, so effectively we already know the plaintext (HTTP, SMTP, ...). CTR mode is malleable so my concern is - when to send the authentication tag? (it is apparently not very effective after every ciphertext block). It can be tempting to check the tag afer end of the transmission, but with continuous stream cipher it may never occur or data could be already processed $\endgroup$ – gusto2 Oct 4 '17 at 14:55
6
$\begingroup$

You can have AES-GCM and streaming at the same time. But:

Do not operate on unauthenticated data!

Treat unauthenticated data like nuclear waste.

The fact that the AES-CTR out of which AES-GCM is built technically can provide access to data before the authentication tag is verified is a red herring. Allowing access to the data before verifying the tag, and requiring a separate API call to verify the tag, is a loaded semiautomatic foot-pointed gun. Don't do it!

Do not allow arbitrarily long messages before you verify authentication tags!

Arbitrarily long messages will tempt you to act on the content of the message before you can verify the authentication tags.

Resist the temptation! Al you have to do is break long messages into chunks of bounded size so that you aren't even tempted to do this. You can even use a chunk sequence number for the AES-GCM nonce, or you can use a scheme like miscreant that handles chunking for you.

Fogeries are bad news! Every program is an interpreter for a programming language that is its input—sometimes that language is Turing-complete, or even if not you may still enable an adversary to control a weird machine you never even thought existed in ways you never imagined. The cryptography lets you ensure that only the peer you're trying to have a conversation with gets to program your program, and not anyone else on the internet.

If the governor of Arkansas acted on a series of forged execution orders, and only afterward checked all the judges' signatures on them, people would be even more upset than they already are about the lethal carceral state. Don't let your program be that governor!

See an earlier answer about xsalsa20poly1305 for elaboration on the performance and denial-of-service implications of bounded-size chunks in a cryptosystem of the same type as AES-GCM.

$\endgroup$
  • 3
    $\begingroup$ Can you specifically answer the question that is related to the crypto primitive (not a protocol)? You're sidestepping some key point and addressing other random aspects (random access? lethal executions?). $\endgroup$ – DeepSpace101 Sep 14 '17 at 19:09
5
$\begingroup$

Using (plain) AES-GCM for streaming data (and, in particular, allowing the receiver to access the plaintext before it has been authenticated) breaks its security guarantee.

Yes, it will "work", in the sense that the data will be correctly transmitted if an attacker doesn't tamper with it. But plain old AES-CTR will do that, too, so if that's all you care about then you might as well just use AES-CTR. Or possibly even no encryption at all.

Allowing the use of an authenticated encryption mode like GCM, but not actually guaranteeing message integrity, just creates a trap for users who may think they're using authenticated encryption even though (because they happened to use the streaming API instead of the non-streaming API) they're actually not. A responsibly designed crypto API should not include such traps.

That said, as Squeamish Ossifrage notes, it is possible to transmit streaming data (relatively) securely using AES-GCM simply by splitting the stream into discrete chunks and authenticating each chunk separately (with appropriate associated data to prevent attackers from shuffling the chunks around). If you want to provide a streaming crypto API based on AES-GCM, that's what you should do.


Note that everything I wrote above applies just as well to any other authenticated encryption modes not specifically designed to support streaming decryption, not just to AES-GCM. That's why you're not getting answers that are specifically about AES-GCM. That said, let me try to briefly address your specific questions:

Can allowing the receiver to access unauthenticated AES-GCM plaintext compromise the AES key?

Not directly.

However, the integrity protection provided by GCM mode does reduce the attack surface (by preventing attacks that involve maliciously modified ciphertext), and it's far for impossible that some system that was otherwise vulnerable to an AES key-recovery attack (due to bugs in other parts of it) might be kept safe by the front-line defense provided by GCM mode.

For example, consider a scenario where the messages consisted of, say, streaming video, and the video codec (which is not normally considered a security-critical part) happened to have a buffer overflow vulnerability that would let a maliciously crafted video stream trigger remote code execution and thereby take over the whole system. Having taken over the system, the attacker could then do anything, including capturing the encryption keys.

Since unauthenticated AES-CTR encryption lets an attacker flip arbitrary bits in the plaintext data, such a vulnerability can be quite easily exploitable (given some known plaintext the attacker can modify). Proper AES-GCM encryption, however, protects the video stream from tampering, and thus prevents such attacks — but only if the GCM authentication token is actually verified before any of the plaintext is passed on to potentially vulnerable code.

A lot of proper cryptosystem design is about minimizing the attack surface and setting up multiple layers of defense in depth, so that errors in non-critical parts of the system cannot be escalated into actual security compromises. In that sense, giving up the message integrity protection offered by GCM mode weakens the overall security of the system by eliminating one layer of defense.

Can allowing the receiver to access unauthenticated AES-GCM plaintext compromise the plaintext itself?

Possibly. Again, this requires exploiting the behavior of the non-crypto parts of the receiving application, but it's potentially easier than key recovery.

For example, even if the attacker cannot actually trigger remote code execution by tampering with the plaintext as described above, they can still inject errors into the plaintext by flipping arbitrary bits in it. By monitoring how the receiver reacts to such errors, they may be able to learn information about the original plaintext. Proper use of GCM mode thwarts this attack by ensuring that all such errors elicit the same response: authentication failure.

Also, if the attacker can learn, through such attacks, the plaintext corresponding to some ciphertext and IV, then they can also trivially decrypt any other ciphertext with the same IV. And of course, without properly enforced message authentication, the attacker is free to choose the IV of their forged messages to be anything they want.

As a worst-case example, imagine that the receiver, upon receiving a garbled message full of errors, will emit an error containing the garbled data they failed to parse. And assume that the attacker can somehow observe these error messages. Then, to decrypt any message, the attacker can simply send a forged message with the same IV as the target message and arbitrary (e.g. random or all-zero) ciphertext. The resulting plaintext will almost surely be garbage, and will thus trigger an error, allowing the attacker to learn the plaintext from the error message. They can then simply XOR the plaintext and the ciphertext to obtain the keystream for that IV, and use that to decrypt the target message.

Will allowing the receiver to access unauthenticated AES-GCM plaintext make the system vulnerable to active forgery attacks?

Yes.

There are plenty of real-world attack scenarios where the attacker isn't interested in decrypting some captured data, but simply in causing the receiver to act based on some forged data of their choosing. And often enough the attacker might not care if the forgery is detected after the data has already been acted upon.

In some cases, e.g. if the only thing the receiver is doing with the unauthenticated data is saving it to a temporary file, it may be possible to securely roll back the system to a safe state when a forgery is detected. But often that's not the case, especially (as noted above) if the data is fed to a subsystem that might have potentially exploitable bugs. In such cases, once the malicious data has been processed and the system has been compromised, there's no way to undo that.

(I believe that's what Squemish Ossifrage's allusion to the death penalty was about. Just as you can't just say "oops, sorry, didn't mean to do that" and un-kill a person after they're dead, you also can't un-compromise a compromised system after it has been taken over and all its secrets have been leaked. You might be able to reinstall the system from scratch, but you can't get the compromised data back.)

If you're not going to verify the authentication tag before allowing the receiver to access the plaintext, is there any point in using AES-GCM in the first place?

I know you didn't actually ask this as such, but I wanted to answer it anyway. And, in my opinion, the answer is a clear "no."

The only advantage of using AES-GCM instead of plain old AES-CTR is that GCM provides message integrity protection, and thereby thwarts active attacks involving message forgery or tampering. If you're not going to actually make use of that protection, you might as well just use AES-CTR. At least then you'll know that you're vulnerable.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.