Subject: Re: [TLS] padding

From: Dave Garrett <[email-masked]>
Date: Fri, 21 Aug 2015 18:32:13 -0400

On Sunday, May 17, 2015 05:29:51 pm Tom Ritter wrote:
> On 17 May 2015 at 14:32, Dave Garrett <[email-masked]> wrote:
> > Is it really necessary to have a separate application_data_padded content type? It'd be simpler to just keep using existing types but amend it with a padding field and require it always be used at minimum to pad up to the nearest multiple of N-bytes. (something low for the default) Additional padding would be optional, but all data would get some minimum.
> 
> That was the first proposal, but the extra bytes on every message for
> people who weren't using padding were deemed to be prohibitive.

Wouldn't it be simpler to just have an optional padding vector that exists only if padding is negotiated? (we already have one optional field with extensions in the hello messages)

A simple method to negotiate would be to add a new HandshakeType with a couple flags, one to indicate that the endpoint will be sending padded messages and another to indicate that it's willing to receive padded messages. Endpoints could declare padding with this message and use it until its peer sends a message requesting otherwise. This sort of scenario would have the additional benefit of not stating the existence of padding in the clear.

Dave

---

From: Russ Housley <[email-masked]>
Date: Sat, 22 Aug 2015 15:36:21 -0400

> A simple method to negotiate would be to add a new HandshakeType with a couple flags, one to indicate that the endpoint will be sending padded messages and another to indicate that it's willing to…

I like the idea that the presence or absence of padding in the ciphertext is hidden in your proposal.  Is there really an need to toggle it on and off?

Russ

---

From: Dave Garrett <[email-masked]>
Date: Sat, 22 Aug 2015 20:28:45 -0400

> I like the idea that the presence or absence of padding in the ciphertext is hidden in your proposal.  Is there really an need to toggle it on and off?

Toggling solves the undesired bandwidth use concern stated by Tom by making it fully optional on both sides. The even simpler route of just having to check if there's bytes in the encrypted fragment other than the payload would avoid a little bit of complexity, but with no way for an endpoint to say no to increased bandwidth usage that it doesn't want to or can't handle. Given this constraint, I'd favor either easily toggleable or always-on, rather than a middle-ground where implementations won't know what they're going to get and can't do anything about it.

A footnote: Negotiating via an extension is probably not a good idea because client extensions will generally be in the clear. That's why I suggest a simple message instead. (there's no need to pad the cleartext hello, so it's fine to wait until record protection is available) Note that I don't think allowing this to be decided after the handshake is a good idea.

A more generalized way to handle throttling padding would be to set a low default and require each endpoint to send a message with a different value, in max bytes per record (or second, or both) of padding permitted, in order to use a different amount. Each endpoint could easily arbitrarily throttle its downstream padding bandwidth independently, if need be.

I'm curious as to how much of a range would actually be useful, though. For actually good protection, you'd really want to pick a stable bandwidth and essentially hold it; keep up/download rates constant or following some consistent pattern with a combination of possibly throttled data and padding such that the data length and time is completely protected and the stream is 100% opaque to an observer. I wouldn't expect this to be all that popular, though, as it would be a bandwidth hog in many cases. A middle-ground might involve also specifying a max bytes allowed in between data bursts to hide the peaks, but now we're getting more complicated than I think we want here if we go any further. (and beyond what I know anything about) The current proposal says that padding algorithms are outside of the scope here, but I think adding this as a built-in feature without coming up with some easily usable default (even if not particularly advanced) is a mistake that will cause this feature to be largely unused.

Dave

---

From: Tom Ritter <[email-masked]>
Date: Mon, 24 Aug 2015 18:22:11 -0500

> A more generalized way to handle throttling padding would be to set a low default and require each endpoint to send a message with a different value, in max bytes per record (or second, or both) of…

I have a not-very-hidden motive in not having it be negotiable: I want
to enable clients to want to send padding be able to do so to any
server, even if that server does not want to pad.  (They can just
discard.)  If it's negotiated, the server may say "I don't support
padding" and clients who want to use it out out of luck.

I do like solutions where the use or non-use of padding is hidden, but
I think in many cases it will be obvious, so the above goal comes
before this goal for me.  I don't believe the topic of encrypting the
content type is completely resolved, but that is a separate proposal:
https://github.com/tlswg/tls13-spec/pull/51

> I'm curious as to how much of a range would actually be useful, though. For actually good protection, you'd really want to pick a stable bandwidth and essentially hold it; keep up/download rates co…

In general, developing good padding approaches is relatively easy for
well defined application protocols, and difficult for extremely
generic ones like "Browsing the Internet".  If one was developing an
application for twitter, google maps, XMPP chat - developing a good
padding mechanism to hide specific actions or data would not have the
same issues.

There's been a number of padding strategies developed by academic
researchers studying traffic correlation/confirmation attacks - I
don't expect any of them is drop-in-good-enough for a generic browser
implementation... but it would be _amazing_ if browser vendors enabled
browser extension authors to choose the padding strategy for
individual origins.  Then we can crowdsource the effort.

-tom

---

From: Stephen Farrell <[email-masked]>
Date: Tue, 25 Aug 2015 00:30:55 +0100

On 25/08/15 00:22, Tom Ritter wrote:
> it would be _amazing_ if browser vendors enabled

Excellent idea!

S.

---

From: Martin Thomson <[email-masked]>
Date: Mon, 24 Aug 2015 17:10:20 -0700

>> individual origins.  Then we can crowdsource the effort.

I believe that this would be possible, but you would have to enumerate
what information you might want to have available.  At the TLS layer,
we've lost a lot of the context.  You might be better off with
HTTP(/2) layer padding.

The

---

From: Dave Garrett <[email-masked]>
Date: Tue, 25 Aug 2015 00:04:35 -0400

The topic of encrypting the content type came up again, and a core WG charter goal is to encrypt as much as possible. To this end, I suggest we consider going all the way in this area: headerless records. Each protected record would contain nothing but an aead-ciphered struct with the bare minimum it needs, namely ContentType & content, plus maybe padding. Nothing else is really needed. The only thing that needs to know anything here is the peer with the key.

struct {
    aead-ciphered struct {
        ContentType type;
        uint16 length = TLSPlaintext.length;
        opaque content[TLSPlaintext.length];
        opaque padding[padding_length];
    };
} TLSCiphertext;

Arbitrary padding can be added after the content, up to the total record maximum size. If we even wanted to ditch the length field, we could do:

struct {
    aead-ciphered struct {
        if (padding_allowed) {
            opaque padding<0..(2^14+256-TLSPlaintext.length)>;
        }
        ContentType type;
        opaque content[TLSPlaintext.length];
    };
} TLSCiphertext;

In which case content is just the remainder of the record after the type. (without the explicit length field, padding needs to come first so it can have its length in its vector first)

Cleartext records would of course be unchanged, as they need to stay as-is for backwards compatibility.

With an encrypted record format like one of the above, everything after the handshake is opaque and potentially padded.

The additional data fed to the AEAD cipher is just the sequence number at this point. The version can easily be mixed into the keying material by adding it to the HKDF label, and then we don't need to re-verify it after the fact if they key depends on it.

Dave

---

From: Martin Thomson <[email-masked]>
Date: Tue, 25 Aug 2015 00:02:42 -0700

>         uint16 length = TLSPlaintext.length;

You can't recover the plaintext without knowing how long it is.  This
part at a minimum needs to be in the clear.  At which point you need
it to be based on TLSCiphertext.length

---

From: Yoav Nir <[email-masked]>
Date: Tue, 25 Aug 2015 11:47:29 +0300

> On Aug 25, 2015, at 2:22 AM, Tom Ritter <[email-masked]> wrote:
> 

I’m not sure having one side send a continuous stream of large record buys you much if the other side doesn’t. Suppose an HTTPS server has 100 resources, each with a different size, it won’t help if the client obscures the identity of the resource it’s asking for if the resource can be identified by its size. Same goes for the existence of traffic. If the server stays quiet until there’s an actual request, the client’s continuous stream of padding-only records is just wasted effort.

IMO this is an argument for negotiation, although even with negotiation we can never be assured that the other side is doing TFC well. 

Yoav

---

From: Kyle Rose <[email-masked]>
Date: Tue, 25 Aug 2015 10:26:24 -0400

> it to be based on TLSCiphertext.length

Is that really true? You could decrypt the first block/few bytes to
get the length (without authentication, of course) and then decrypt
the remainder according to this candidate length. Then authenticate
the entire record to make sure the candidate length was correct.

(I am not claiming anything about the purity of this approach, only
that it is technically feasible.)

Kyle

---

From: Viktor Dukhovni <[email-masked]>
Date: Tue, 25 Aug 2015 14:42:11 +0000

> that it is technically feasible.)

SSH now has ciphersuites where the payload length is encrypted,
IIRC via a key that is different from the payload key.

-- 
	Viktor.

---

From: Martin Thomson <[email-masked]>
Date: Tue, 25 Aug 2015 08:26:35 -0700

> the entire record to make sure the candidate length was correct.

That depends on the aead - and the implementation. GCM can - maybe - be
broken apart that way*, but I can't think that going to all the trouble of
formulating an aead just to break it open at the first point that it
becomes inconvenient.

You could imagine an aead that made that difficult or impossible (just
reverse the order of the bytes...). Or, without imagining at all, you can
have hardware module that enforce authentication before releasing plaintext.

---

From: Martin Thomson <[email-masked]>
Date: Tue, 25 Aug 2015 08:28:44 -0700

> IIRC via a key that is different from the payload key.
Yeah, I'm not that enthusiastic about that feature, but if you want more
complexity, it is possible. The authentication properties are interesting
there, of course.