Subject: [openpgp] AEAD Chunk Size

From: "Neal H. Walfield" <[email-masked]>
Date: Wed, 27 Feb 2019 11:51:51 +0100

The current version of 4880bis has a chunk size parameter for AEAD:

  ## AEAD Encrypted Data Packet (Tag 20)

  ...

  The body of this packet consists of:

  ...

    * A one-octet chunk size.

  ...

  The chunk size octet specifies the size of chunks using the
  following formula (in C), where c is the chunk size octet:

       chunk_size = ((uint64_t)1 << (c + 6))

  An implementation MUST support chunk size octets with values from 0
  to 56.  Chunk size octets with other values are reserved for future
  extensions.  Implementations SHOULD NOT create data with a chunk
  size octet value larger than 21 (128 MiB chunks) to facilitate
  buffering of not yet authenticated plaintext.

  https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-05#section-5.16

In other words, chunks can be up to 1 << (56 + 6) = 2^62 bytes large
(4 exbibytes).

According to RFC 5116, an AEAD algorithm must not output partially
decrypted data:

   If a
   particular implementation of an AEAD algorithm is requested to
   process an input that is outside the range of admissible lengths, or
   an input that is outside the range of lengths supported by that
   implementation, it MUST return an error code and it MUST NOT output
   any other information.  In particular, partially encrypted or
   partially decrypted data MUST NOT be returned.

   https://tools.ietf.org/html/rfc5116#section-2.1

Because it is hard to know the context (i.e., the available resources)
in which a message will be decrypted, it is difficult for an
implementation to make a reasonable choice when doing the encryption.
Actually, I'm not aware of any advantages for chunk sizes that are
larger than a few kilobytes.

Consequently, I propose not only imposing a reasonable ceiling on the
chunk size that even small embedded devices with a cortex M0 could
handle, but to simply fix the parameter to 16 KiB.  It's not clear to
me that a variable size offers any advantages.  But, there is a clear
disadvantage: it's unjustified complexity, which is a breeding ground
for bugs.  Unless someone can justify this added complexity, I see no
reason to parameterize this.

(If it is needed, the size could be a function of the actually AEAD
algorithm, e.g., EAX, OCB, etc.)

I've attached a patch that makes the proposed change.

I've spoken with several people including Vincent Breitmoser (Open
Keychain), Justus Winter & Kai Michaelis (also Sequoia), Phil
Zimmermann, and Hanno Böck and they all support this proposal.

Thanks,

:) Neal

From efd12443c2da194fdb40eb6f606c9d9bb9c46ddc Mon Sep 17 00:00:00 2001
From: "Neal H. Walfield" <[email-masked]>
Date: Wed, 27 Feb 2019 11:32:11 +0100
Subject: [PATCH] Fix the AEAD chunk size to 16 kiByte.

---
 middle.mkd | 21 +++++----------------
 1 file changed, 5 insertions(+), 16 deletions(-)

diff --git a/middle.mkd b/middle.mkd
index 44d1246..4437df7 100644
--- a/middle.mkd
+++ b/middle.mkd
@@ -2694,8 +2694,6 @@ The body of this packet consists of:
 
   * A one-octet AEAD algorithm.
 
-  * A one-octet chunk size.
-
   * A starting initialization vector of size specified by the AEAD
     algorithm.
 
@@ -2716,11 +2714,11 @@ a full authentication tag.
 
 For each chunk, the AEAD construction is given the Packet Tag in new
 format encoding (bits 7 and 6 set, bits 5-0 carry the packet tag),
-version number, cipher algorithm octet, AEAD algorithm octet, chunk
-size octet, and an eight-octet, big-endian chunk index as additional
+version number, cipher algorithm octet, AEAD algorithm octet,
+and an eight-octet, big-endian chunk index as additional
 data.  The index of the first chunk is zero.  For example, the
-additional data of the first chunk using EAX and AES-128 with a chunk
-size of 64 kiByte consists of the octets 0xD4, 0x01, 0x07, 0x01, 0x10,
+additional data of the first chunk using EAX and AES-128
+consists of the octets 0xD4, 0x01, 0x07, 0x01,
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, and 0x00.
 
 After the final chunk, the AEAD algorithm is used to produce a final
@@ -2729,16 +2727,7 @@ given the additional data specified above, plus an eight-octet,
 big-endian value specifying the total number of plaintext octets
 encrypted.  This allows detection of a truncated ciphertext.
 
-The chunk size octet specifies the size of chunks using the following
-formula (in C), where c is the chunk size octet:
-
-        chunk_size = ((uint64_t)1 << (c + 6))
-
-An implementation MUST support chunk size octets with values from 0 to
-56.  Chunk size octets with other values are reserved for future
-extensions.  Implementations SHOULD NOT create data with a chunk size
-octet value larger than 21 (128 MiB chunks) to facilitate buffering of
-not yet authenticated plaintext.
+The chunk size is 16 kiByte.
 
 A new random initialization vector MUST be used for each message.
 Failure to do so for each message will lead to a catastrophic failure
-- 
2.11.0

---

From: Vincent Breitmoser <[email-masked]>
Date: Wed, 27 Feb 2019 12:25:38 +0100

Thanks for bringing this up, Neal. I do support this motion.

For the record, related merge request is here:
https://gitlab.com/openpgp-wg/rfc4880bis/merge_requests/16

 - V

---

From: Bart Butler <[email-masked]>
Date: Wed, 27 Feb 2019 21:34:09 +0000

Hi all,

We (Sunny Rajan and I) definitely agree with reducing the range of allowed sizes, because both 4 exabyte chunks and large messages composed of 64-byte chunks are clearly not optimal.

In our AEAD implementation for OpenPGP.js we settled on a default `c` of 12 rather than 8 after some performance benchmarking showed that 256 kiB chunks were more performant for the most common message sizes. Our result was specific to the web crypto API, and therefore specific to OpenPGP.js, but in general libraries may want to use different default sizes depending on implementation details like this.

So ideally we’d prefer to keep the size byte, but to shrink its range in both directions. For example, the RFC could state that the chunk SHOULD be 16 kiB (or 256 kiB, hint hint), but decryption MUST be available for `c` values between 8-12 inclusive. This would also allow us to be backwards-compatible with messages that have already been created following the current version of the draft, which do exist given the benefit that AEAD provides and that OpenPGP.js has supported the current draft in experimental mode for most of the last year. 

Regards,

Bart and Sunny

‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐
On Wednesday, February 27, 2019 3:25 AM, Vincent Breitmoser <[email-masked]> wrote:

>     "Neal H. Walfield" [email-masked] wrote:
>     

> > AEAD Encrypted Data Packet (Tag 20)
> > 

> > ------------------------------------
> > 

> > From: "Neal H. Walfield" [email-masked]

> > -   A one-octet AEAD algorithm.
> > 

> > -   -   A one-octet chunk size.
> > -   -   A starting initialization vector of size specified by the AEAD
> >         algorithm.
> >         

> > -------------------------------------------------------------------------------------------------------------------------
> > 

> openpgp mailing list
> [email-masked]
> https://www.ietf.org/mailman/listinfo/openpgp

---

From: Jon Callas <[email-masked]>
Date: Wed, 27 Feb 2019 14:37:20 -0800

> On Feb 27, 2019, at 1:34 PM, Bart Butler <bartbutler=[email-masked]> wrote:
> 
> Hi all,
> 

I think this is a reasonable way to have it to put an upper limit with a SHOULD.

I believe that if we limit it to 16K, we *will* regret that, for performance or other reasons. And while some of the upper sizes are presently absurdly large, one never knows what happens a couple decades from now. 

Moreover, forbidding it says that we state now that no one could ever have a reasonable use; my experience is that categorical statements like that are just asking the fates to bite us in an uncomfortable place. Amazon S3 increased their max object size to 5TB a few years ago. I’m not saying it should be that large, but I think this is a pretty convincing argument that 16K is too small.

So I think that a SHOULD is the right way to put it. I care less about what the SHOULD limit should be, but a small hard limit sounds like a bad idea.

	Jon

---

From: Bart Butler <[email-masked]>
Date: Wed, 27 Feb 2019 23:00:13 +0000

Hi Jon,

Do I understand correctly that you oppose shrinking the allowable range with MUST at all too? I think the argument for this is fairly convincing from a usage perspective to ensure that someone decrypting a large message is not obligated to download a huge amount of data before finding out that it is corrupted or otherwise has been tampered with. Likewise, we had to address unanticipated performance issues in OpenPGP.js with very small chunks which could have allowed a bad actor to essentially DoS the library with a strangely-constructed message.

In other words, I'm not really swayed by the implementation simplification argument but I do think that very small or very large chunk size, in addition to *probably* being useless, pose a real threat in terms of abuse.

So I think having a MUST for the range, maybe 16kiB to 256 kiB, or 16 kiB to 1024 kiB is a reasonable thing to do. And as long as we keep the size byte, we can always increase the upper limit of the range in the future if needed.

Bart

‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐
On Wednesday, February 27, 2019 2:37 PM, Jon Callas <[email-masked]> wrote:

> > On Feb 27, 2019, at 1:34 PM, Bart Butler bartbutler=[email-masked] wrote:
> > Hi all,

> I believe that if we limit it to 16K, we will regret that, for performance or other reasons. And while some of the upper sizes are presently absurdly large, one never knows what happens a couple decades from now.
>

---

From: Jon Callas <[email-masked]>
Date: Wed, 27 Feb 2019 16:03:10 -0800

> On Feb 27, 2019, at 3:00 PM, Bart Butler <[email-masked]> wrote:
> 
> Hi Jon,
> 

My warning is against shooting someone else in the foot, or forcing them to use some other protocol.

Thus, saying (e.g.) that the range MUST be between 1K and 16K is a bad idea; we even know now that 256K has in some cases an efficiency advantage. You can say, MUST support 1K to 16K, SHOULD support up to 256K and MAY support larger sizes. There can also be a couple of paragraphs to explain that there are good reasons neither to be very small nor very large.

My concern is someone saying something like, “Gosh, I’d like to have OpenPGP AEAD encryption for S3 Objects, but I can’t ‘cause those go up to 5TB.” Anyone who’s going to use 5TB objects probably knows the headaches they inherit and yeah, you aren’t going to do that on a Cortex M0.

Does this make sense?

	Jon

---

From: Ronald Tse <[email-masked]>
Date: Thu, 28 Feb 2019 00:34:42 +0000

And this is a very reasonable approach. I support Jon’s take on this.

_____________________________________

Ronald Tse
Ribose Inc.

+=========================================================+
This message may contain confidential and/or privileged
information.  If you are not the addressee or authorized to
receive this for the addressee, you must not use, copy,
disclose or take any action based on this message or any
information herein.  If you have received this message in
error, please advise the sender immediately by reply e-mail
and delete this message.  Thank you for your cooperation.
+=========================================================+

On Feb 28, 2019, at 8:03 AM, Jon Callas <joncallas=[email-masked]<mailto:joncallas=[email-masked]>> wrote:

---

From: Ronald Tse <[email-masked]>
Date: Thu, 28 Feb 2019 00:35:19 +0000

And thanks Neal for the suggestion!

Ronald Tse
Ribose Inc.

> On Feb 28, 2019, at 8:03 AM, Jon Callas <joncallas=[email-masked]> wrote:
> 
> 
> 
> _______________________________________________
> openpgp mailing list
> [email-masked]

---

From: Bart Butler <[email-masked]>
Date: Thu, 28 Feb 2019 00:45:52 +0000

‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐
On Wednesday, February 27, 2019 4:03 PM, Jon Callas <[email-masked]> wrote:

> > On Feb 27, 2019, at 3:00 PM, Bart Butler [email-masked] wrote:
> > Hi Jon,
> > In other words, I'm not really swayed by the implementation simplification argument but I do think that very small or very large chunk size, in addition to probably being useless, pose a real threat in terms of abuse.

> Thus, saying (e.g.) that the range MUST be between 1K and 16K is a bad idea; we even know now that 256K has in some cases an efficiency advantage. You can say, MUST support 1K to 16K, SHOULD suppor…

The problem is that MAY for either very small or very large chunks sizes in some ways forces library maintainers to have support for these chunk sizes because they WILL appear in the wild, and then there will be complaints if they do not decrypt. If they are technically legal then everyone has to account for these edge cases in their apps--i.e., a 1-chunk AEAD multi-gigabyte movie which you technically can't start playback until the whole thing has been downloaded and buffered because the authentication is only at the end.

> Jon

It does, and normally on this kind of thing I would completely agree with you, but in this case I think there are two mitigating factors:

1. AEAD chunk size does not limit message/file size in any meaningful way assuming we set the upper limit chunk size to something reasonable like 1024 kiB, you just use multiple chunks, which is the idea anyway.
2. Abuse potential in an open standard

It's #2 which is really compelling for me for exactly the reason that we DO want this to be usable for arbitrary uses and message sizes in federated contexts, and for that to be possible we need to try to set reasonable limits to prevent malicious or careless users from creating bad-but-legal payloads.

---

From: Hanno Böck <[email-masked]>
Date: Thu, 28 Feb 2019 09:18:59 +0100

On Wed, 27 Feb 2019 16:03:10 -0800
Jon Callas <joncallas=[email-masked]> wrote:

> Thus, saying (e.g.) that the range MUST be between 1K and 16K is a
> bad idea; we even know now that 256K has in some cases an efficiency
> advantage. You can say, MUST support 1K to 16K, SHOULD support up to
> 256K and MAY support larger sizes. There can also be a couple of
> paragraphs to explain that there are good reasons neither to be very
> small nor very large.

This sounds like a recipe to create multiple incompatible
implementations. That is certainly not what anyone should want.

> My concern is someone saying something like, “Gosh, I’d like to have
> OpenPGP AEAD encryption for S3 Objects, but I can’t ‘cause those go
> up to 5TB.”

Sorry, I don't understand the comparison here.
We're talking about encryption chunk sizes, not sizes of total
encrypted content.
Nothing here's going to limit the size of the objects you can encrypt.

-- 
Hanno Böck
https://hboeck.de/

mail/jabber: [email-masked]
GPG: FE73757FA60E4E21B937579FA5880072BBB51E42

---

From: "Neal H. Walfield" <[email-masked]>
Date: Thu, 28 Feb 2019 09:38:36 +0100

Hi Bart,

Thanks for your feedback.

On Wed, 27 Feb 2019 22:34:09 +0100,
Bart Butler wrote:
> In our AEAD implementation for OpenPGP.js we settled on a default
> `c` of 12 rather than 8 after some performance benchmarking showed
> that 256 kiB chunks were more performant for the most common message
> sizes. Our result was specific to the web crypto API, and therefore
> specific to OpenPGP.js, but in general libraries may want to use
> different default sizes depending on implementation details like
> this.

I don't need exact numbers, but I'd appreciate it if you could you
comment on the approximate performance of 256 kiB chunks relative to
16 kiB chunks (e.g., factor 1.2 speedup).  Of course, if you still
have the numbers lying around, that would be even better!

There are two reasons that I find 16 kiB *intuitively* appealing from
a performance perspective: a typical L2 cache is about 256 kiB these
days.  So a 16 kiB buffer has a good chance of staying completely in
L2.  Second, on all desktop and mobile operating systems, it is almost
always reasonable to stack allocate a 16 kiB buffer whereas 256 kiB is
a bit big.

From a robustness perspective, I'd like to avoid introducing a
threshold and having to do something brittle like:

  void *buffer;
  if size > 16 kiB {
    buffer = malloc(size);
  } else {
    buffer = alloca(size);
  }

  ...

  if size > 16 kiB {
    free(buffer);
  }

Unfortunately, I haven't benchmarked this type of thing in the context
of AEAD so this is just drawing from my limited prior experience with
sizing these sorts of things.

:) Neal

---

From: "Neal H. Walfield" <[email-masked]>
Date: Thu, 28 Feb 2019 09:42:34 +0100

Bart Butler wrote:
> So ideally we’d prefer to keep the size byte, but to shrink its
> range in both directions. For example, the RFC could state that the
> chunk SHOULD be 16 kiB (or 256 kiB, hint hint), but decryption MUST
> be available for `c` values between 8-12 inclusive. This would also
> allow us to be backwards-compatible with messages that have already
> been created following the current version of the draft, which do
> exist given the benefit that AEAD provides and that OpenPGP.js has
> supported the current draft in experimental mode for most of the
> last year.

Could you please comment on the approximate number of messages that
have been sent with AEAD?  Is protonmail doing AEAD exclusively these
days?

As a compromise, I'd be willing to leave the byte, but have it be a
magic value whose value must be X (where X is say, 8 or 12).  Then you
can detect X=12 and not error out for your users.  But, I'm not yet
convinced that a range is a good idea.

---

From: "Neal H. Walfield" <[email-masked]>
Date: Thu, 28 Feb 2019 09:51:12 +0100

On Wed, 27 Feb 2019 23:37:20 +0100,
Jon Callas wrote:
> Moreover, forbidding it says that we state now that no one could
> ever have a reasonable use; my experience is that categorical
> statements like that are just asking the fates to bite us in an
> uncomfortable place. Amazon S3 increased their max object size to
> 5TB a few years ago. I’m not saying it should be that large, but I
> think this is a pretty convincing argument that 16K is too small.

I think you misunderstand the point of the chunk size parameter.

Modulo perhaps performance, the chunk size is not visible to the
application.  That is, messages encrypted using AEAD can
(theoretically) still be 4 exibyte large when using a 16 kiB chunk
size; a message can consist of any number of chunks.  Chunk size is
like HTTP's chunked transfer encoding or OpenPGP's partial body
lengths.

The reason that we don't want large chunk sizes is that when
decrypting a chunk, the chunk MUST (RFC 5116) be buffered.  Since the
encryptor generally doesn't know the context in which the decryption
will occur, it must be conservative and choose a small chunk size.
Otherwise, a decryptor will inevitably encounter a chunk size that it
can't buffer and gratuitously fail.  Alternatively, it violates the
must and outputs the decrypted data without first verifying it thereby
resulting in the next EFAIL.

> So I think that a SHOULD is the right way to put it. I care less
> about what the SHOULD limit should be, but a small hard limit sounds
> like a bad idea.

Do you still think a hard upper limit is a bad idea?

---

From: "Neal H. Walfield" <[email-masked]>
Date: Thu, 28 Feb 2019 09:53:53 +0100

On Thu, 28 Feb 2019 00:00:13 +0100,
Bart Butler wrote:
> So I think having a MUST for the range, maybe 16kiB to 256 kiB, or
> 16 kiB to 1024 kiB is a reasonable thing to do. And as long as we
> keep the size byte, we can always increase the upper limit of the
> range in the future if needed.

If we keep the size byte with the justification that we might increase
the range in the future, some implementations will decide to support
other chunk sizes to be future compatible.  I think this is a
disastrous idea.  If we need to change the chunk size in the future,
let's just create a new packet, AEADv2.

:) Neal

---

From: "Neal H. Walfield" <[email-masked]>
Date: Thu, 28 Feb 2019 09:56:02 +0100

On Thu, 28 Feb 2019 01:45:52 +0100,
> It's #2 which is really compelling for me for exactly the reason that we DO want this to be usable for arbitrary uses and message sizes in federated contexts, and for that to be possible we need to…

I fully agree with #2.  I am convinced that it is imperative that we
avoid introducing potential attack surfaces that have no value.

---

From: Jon Callas <[email-masked]>
Date: Thu, 28 Feb 2019 10:39:17 -0800

> On Feb 28, 2019, at 12:51 AM, Neal H. Walfield <[email-masked]> wrote:
> 

Perhaps I do misunderstand, but that’s kinda what I was expecting; an equivalent to the old streaming chunks.

> Do you still think a hard upper limit is a bad idea?

No, I don’t think a hard upper limit is a bad idea. In the text you quote above, I said a *small* hard upper limit. And no, I don’t know what small means. I think 16K is small. 256K might be small. AES-GCM has issues about 64G. One might argue that’s a reasonable large upper limit. Me, I think anything in the few megabytes to a gigabyte-ish is just fine.

Let me rewind a bit and get to my real point which I don’t think I’m making well.

When one creates a standard, one needs to be careful with parameters, particularly the MUSTs. Seemingly sensible things can have downstream effects that convince people to use some other protocol. Worse, someone’s angry blog post about something can quickly go into “not even wrong” territory and embed itself into folklore and you can’t get it out. There are plenty of bad ideas that someone else has a really reasonable use case for.

The Partial Body Lengths that OpePGP has had from the beginning have no restrictions on them. There’s non-normative guidance that pretty much says you shouldn’t even use them, but there’s no restriction on size. This has never caused a problem that I’m aware of. I’m sure it caused a problem that none of us are aware of, and the implementors just solved it on their own. It is this experience that has me wondering about what the restrictions out to be.

The best way to deal with it in a standard is to have non-normative guidance. It is non-normative guidance that I was suggesting. Let me write an example bit of non-normative guidance below:

- - - - -

Implementations should pick a chunk size with care. Depending on the AEAD algorithm, large chunk sizes may limit the ability to process chunks, particularly with an AEAD algorithm that is not single-pass, and thus the system decrypting it must hold the entire chunk as it decrypts it. In general, the chunk size is irrelevant to any code outside of the chunk handling code, so smaller is better.

An implementation SHOULD pick a chunk size of 256KiB or less. An implementation MAY use larger sizes, but this could limit interoperability with resource-limited systems and should be done with care.

- - - - -

I don’t think that’s perfect, but it’s okay as a first draft. I would completely support something like the text above. I’d support it if it said 16KiB too. I’ll also support hard limits, but my intuition is that that decision will come with frustration for someone else.

Does this make more sense?

	Jon

---

From: Bart Butler <[email-masked]>
Date: Thu, 28 Feb 2019 19:11:06 +0000

> There are two reasons that I find 16 kiB intuitively appealing from

> :) Neal

So, quoted from Daniel Huigens, who did the original benchmarking:

"Re. Neal's request, I didn't have the numbers anymore, so I unscientifically created some new ones

It looks like either Chrome or we have actually fixed the performance issues there with c=8 since the last time I tested it, as for most message sizes the performance is the same as c=12 or even a bit faster, except 128KB-256KB, which fits in one chunk with c=12 and there c=8 is about 1.1x - 1.5x slower.

In Firefox, for >=64KB messages, c=8 is still about 1.5x - 2.5x slower than c=12, however, it looks like most of the overhead of smaller chunks comes from the streams polyfill, not the web crypto API. So that should probably be possible for us to fix."

I see your logic on 16 kiB but in particular for file encryption I think there's some value to being able to go bigger in the future (L2 cache sizes have changed in the last 20 years as well and will probably change in the next two decades), and to keep the size byte to be able to configure this rather than have an entirely new packet. I think a SHOULD for 16 kiB though is totally appropriate now though for the reasons you mentioned.

---

From: Bart Butler <[email-masked]>
Date: Thu, 28 Feb 2019 19:28:36 +0000

On Thursday, February 28, 2019 10:39 AM, Jon Callas <[email-masked]> wrote:

> Jon

What do you think about this? I made the last sentence a bit scarier and introduces the lower recommendation as well:

Implementations should pick a chunk size with care. Depending on the AEAD algorithm, large chunk sizes may limit the ability to process chunks, particularly with an AEAD algorithm that is not single-pass, and thus the system decrypting it must hold the entire chunk as it decrypts it. Small chunk sizes may introduce unnecessary overhead in decryption. In general, the chunk size is irrelevant to any code outside of the chunk handling code.

An implementation SHOULD pick a chunk size between 16KiB and 256KiB (c between 8 and 12). An implementation SHOULD refuse to process chunks outside this size range in federated or untrusted contexts.

---

From: Bart Butler <[email-masked]>
Date: Thu, 28 Feb 2019 19:44:41 +0000

> have been sent with AEAD? Is protonmail doing AEAD exclusively these

I can't because I do not know--it's an experimental feature in OpenPGP.js. I do know that some users of the library are using it internally in closed systems, and we'd prefer not to break decryption for their existing messages but also prefer not to keep supporting an obsolete draft. You could argue that they shouldn't have used an experimental feature for production but given how overdue AEAD is for PGP I find it difficult to blame them myself.

ProtonMail doesn't use V5 keys yet at all, as we exist within the federated email ecosystem and it would break compatibility. So this is not coming from us personally, just on behalf of the OpenPGP.js community in general.

---

From: "brian m. carlson" <[email-masked]>
Date: Fri, 1 Mar 2019 00:26:22 +0000

> I don’t think that’s perfect, but it’s okay as a first draft. I would completely support something like the text above. I’d support it if it said 16KiB too. I’ll also support hard limits, but my in…

I think this is a good first start. However, I think we need to specify
some guidelines about what sizes are required for interoperability. I'm
happy to give people guidance, but if we state that chunk sizes up to
256 KiB (or whatever size we decide) are required to be supported, then
we let people decide whether performance or interoperability is more
important for their use case.

So I'd specify a sentence at the beginning of the second paragraph that
says, "An implementation MUST support chunk sizes up to 256 KiB."
-- 
brian m. carlson: Houston, Texas, US
OpenPGP: https://keybase.io/bk2204