Re: [openpgp] AEAD Chunk Size

Jon Callas <> Sat, 30 March 2019 23:09 UTC

Return-Path: <>
Received: from localhost (localhost []) by (Postfix) with ESMTP id 1CACC1200A3 for <>; Sat, 30 Mar 2019 16:09:46 -0700 (PDT)
X-Virus-Scanned: amavisd-new at
X-Spam-Flag: NO
X-Spam-Score: -1.849
X-Spam-Status: No, score=-1.849 tagged_above=-999 required=5 tests=[BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, FREEMAIL_FROM=0.001, KHOP_DYNAMIC=0.85, RCVD_IN_DNSWL_LOW=-0.7, SPF_PASS=-0.001, URIBL_BLOCKED=0.001] autolearn=ham autolearn_force=no
Authentication-Results: (amavisd-new); dkim=pass (2048-bit key)
Received: from ([]) by localhost ( []) (amavisd-new, port 10024) with ESMTP id 94ehAPzJhqAg for <>; Sat, 30 Mar 2019 16:09:43 -0700 (PDT)
Received: from ( []) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by (Postfix) with ESMTPS id C08FB1202D2 for <>; Sat, 30 Mar 2019 16:09:43 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;; s=04042017; t=1553987382; bh=2DgOgL+N2p43kJDThxc//ziPwrYMvUOzN4bulexNsdA=; h=Content-Type:Mime-Version:Subject:From:Date:Message-Id:To; b=Rr1ybGr4XtYpEUPtTbhrrCFslkpvjIU0yvYTLPTFmbZ2QY94rFVm6XrFUWCL+71pk 1BwQnHtmdQAyFM2XvHmLOn96xZzU2Vqv3wefAreCH4ImUaCoLB1dWY+/l7vVBmHj0X EKL0aJxxLQdfBOJHzc2JANVnu5WfyX2v3wheu+uWq/0N3kiu3EQi+52VO1B6VrfEe5 DfkwBNWPvPkDnzGRPbp5xSTCrKMY3S1/QWQT+04afqJ/ONMlA7tmVcKy8uKyVM/xs/ c+Xe2jOBtEKRqWpurgmxcU/Z9QiMHzYxyMPtGP+vCEEWiGNALr9vZGGsLsDeU323jW 5Rtb7nlnEg79Q==
Received: from [] ( []) by (Postfix) with ESMTPSA id A3E07A0000B; Sat, 30 Mar 2019 23:09:42 +0000 (UTC)
Content-Type: text/plain; charset=utf-8
Mime-Version: 1.0 (Mac OS X Mail 12.2 \(3445.102.3\))
From: Jon Callas <>
In-Reply-To: <>
Date: Sat, 30 Mar 2019 16:09:41 -0700
Cc: Jon Callas <>, "Neal H. Walfield" <>, "" <>, Justus Winter <>, Peter Gutmann <>
Content-Transfer-Encoding: quoted-printable
Message-Id: <>
References: <> <> <> <> <> <>
To: Bart Butler <>
X-Mailer: Apple Mail (2.3445.102.3)
X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:, , definitions=2019-03-30_11:, , signatures=0
X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 suspectscore=0 malwarescore=0 phishscore=0 bulkscore=0 spamscore=0 clxscore=1015 mlxscore=0 mlxlogscore=999 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1812120000 definitions=main-1903300170
Archived-At: <>
Subject: Re: [openpgp] AEAD Chunk Size
X-Mailman-Version: 2.1.29
Precedence: list
List-Id: "Ongoing discussion of OpenPGP issues." <>
List-Unsubscribe: <>, <>
List-Archive: <>
List-Post: <>
List-Help: <>
List-Subscribe: <>, <>
X-List-Received-Date: Sat, 30 Mar 2019 23:09:46 -0000

> On Mar 29, 2019, at 7:17 PM, Bart Butler <> wrote:
> Hi Jon,
> As others have noted, there is a lot of confusion on this thread, some of which you touched in your AEAD Conundrum message, like when we say AEAD should not release unauthenticated plaintext, do we mean the entire message or the chunk?

That is precisely the question. But the bigger question is whether you care about that. Sometimes it matters, sometimes it does not.

For example, let’s suppose that I have a very large blob on mass storage. Media failures happen. If there’s a bad block on a disk, do you want to lose the whole file because of it? Sometimes you want to throw your hands up in the air. This is most common in an interactive protocol, and in general the answer is yes. For example, an SSL connection to a server, if there’s funny business going on, you want to blow up the connection and try over again. On the other hand, if you had an archival thing (e.g. tar file with some historic documents), you want to recover as much as you can.

OpenPGP is in general the latter case rather than the former. I believe it’s less important to have strict semantics on failures because it’s usually storage.

> Another piece of confusion is that Efail isn't a single vulnerability, it was several vulnerabilities related (at best) thematically.

I understand Efail. Trust me.

> So to be very specific, for the purpose of the following discussion, the advantage of smaller AEAD chunks is specifically to prevent Efail-style ciphertext malleability/gadget attacks, and the prohibition on releasing unauthenticated plaintext is applied to individual chunks, which is sufficient to foil this kind of attack in email.

I disagree. If you want to prevent something like Efail, you want larger chunks. Assuming that you believe that early release matters. 

Let’s rewind here, and not talk about Efail, let’s talk about the real issue. If you want the entire blob to have all-or-nothing semantics, then you want the fewest number of chunks as is reasonable. If you have attacker-controlled inputs, then every joint between the chunks is a vulnerability.

> The kind of attack we are talking about is fundamentally about exfiltration of plaintext data to an attacker-controlled endpoint. Borrowing from your AEAD Conundrum message, if the first chunk passes and is released, and the second chunk fails, that is OK, at least for email, because the part that was modified (the second chunk) is never released, so you get a truncated message and an error, but the truncated message without the modifications isn't going to exfiltrate itself.

I agree with this. 

> Now if releasing ANY authenticated chunk of a message that hasn't been fully authenticated (in an AEAD sense) is a real problem for your application, I'd argue that you're trying to make AEAD do something it's not suited for and you should enforce this in your application if it applies to you, probably by not streaming.
> So to recap, small-chunk AEAD provides specific value in preventing ciphertext malleability/gadget attacks, particularly in HTML email, which is a common use case.

Also agree 100%.

This is why a long time ago, I said that Efail is orthogonal to the chunking issue. Either way, large or small, you end up in the same place of not being hacked.

> What value does large-chunk AEAD actually provide? What I'm getting from the AEAD Conundrum message is that it's a way for the message encrypter to leverage the "don't release unauthenticated chunks" prohibition to force the decrypter to decrypt the whole message before releasing anything. Why do we want to give the message creator this kind of power? Why should the message creator be given the choice to force her recipient to either decrypt the entire message before release or be less safe than she would have been with smaller chunks?

Let me summarize the conundrum: If you want strict AEAD no-release semantics, you want a fewer number of chunks. 

> Coming back to Neal's point, it's really hard to see any sort of value in really large AEAD chunks, because the performance overhead is negligible at that point and the only security 'benefit' that I can see is the encrypter trying to use the spec to force the decrypter to not stream, which does not seem like something at all desirable.

Okay, here’s another thing that’s a pet peeve of mine. We’re arguing security and you brought up performance. I never mentioned performance, the people who want large chunks haven’t brought it up. They want large chunks because they perceive it to be more secure. 

If you respond to a security request with a performance answer, you literally don’t know what you’re talking about. So let’s toss that aside.

Bigger chunks *are* more secure. Does that security matter? Well, it does to the people who want big chunks.

> -Bart
> P.S. ProtonMail doesn't use V5 keys or the new draft yet, but some users of OpenPGP.js have started using them with 256kB chunks, so we are not arguing on behalf of ourselves for the 256kB chunk size. The proposed language seems more or less OK in this regard, as most implementations will presumably keep 256kB support so these early adopters will not lose interoperability with their messages.

I am going to rewind again, back to the proposal I made. Here it is, so we can look at it. 

* MUST support 16KB chunks.
* SHOULD support 256K chunks, as these are common (Protonmail).
* MAY support larger up to the present very large size.
* MAY reject or error out on chunks larger than 16KB, but repeating ourselves, SHOULD support 256K.

Elided out of this, and possibly important is that “support” includes chunks smaller than that size. I should have said that, but I wanted it to be as stark as possible. So let me repeat it and abstract it with some variables:

(1) MUST support up to <small-chunk-size> chunks.
(2) SHOULD support up to <larger-chunk-size> chunks, as these are common.
(3) MAY support larger up to the present very large size.
(4) MAY reject or error out on chunks larger than <small-chunk-size>, but repeating ourselves, SHOULD support <larger-chunk-size>.

Clauses (3) and (4) set up a sandbox for the people who want very large chunks. They can do whatever they want, and the rest of us can ignore them. Why get rid of that? It doesn’t add any complexity to the code. It lets the people who want the huge ones do them in their own environment and not bother other people.

My concern is over (1) and (2) and specifically that there’s both <small> and <large> sizes. 

I think that’s an issue. If there are two numbers we are apt to end up with skew before settling on one, so it’s better to agree on just one. That’s the real wart in my proposal.

Neal said he’s fine with 256K. We could do that. 16K has also been suggested (I think Neal said it’s his preference). My intuition is that whatever GnuPG is using for partial body lengths is also a good option as we know that that’s reasonable for both performance and everything else, and my preference is that it be as small as possible to support the smallest footprint possible. I spent about ten minutes looking for the answer and I think it’s 8K, but I’m not sure. Someone correct me if that’s not it. Whatever it is, that’s what I’d do, but I’m not an implementer.

Opinions on what a single number should be? 256? 16? 8? Something else?