Re: [TLS] Encrypting record headers: practical for TLS 1.3 after all?

Fabrice Gautier <> Wed, 02 December 2015 19:44 UTC

Return-Path: <>
Received: from localhost ( []) by (Postfix) with ESMTP id 49D441B2A0F for <>; Wed, 2 Dec 2015 11:44:13 -0800 (PST)
X-Virus-Scanned: amavisd-new at
X-Spam-Flag: NO
X-Spam-Score: -1.998
X-Spam-Status: No, score=-1.998 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, HTML_MESSAGE=0.001, MIME_QP_LONG_LINE=0.001, SPF_PASS=-0.001] autolearn=ham
Received: from ([]) by localhost ( []) (amavisd-new, port 10024) with ESMTP id wZk2Jv1RyKfO for <>; Wed, 2 Dec 2015 11:44:10 -0800 (PST)
Received: from ( [IPv6:2607:f8b0:400e:c00::22d]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by (Postfix) with ESMTPS id 447081B29CE for <>; Wed, 2 Dec 2015 11:44:10 -0800 (PST)
Received: by pfdd184 with SMTP id d184so1498256pfd.3 for <>; Wed, 02 Dec 2015 11:44:09 -0800 (PST)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;; s=20120113; h=content-type:mime-version:subject:from:in-reply-to:date:cc :content-transfer-encoding:message-id:references:to; bh=Ypei/GpiVTD4EjVb64IONbyKpoZhGw7dhu7THsKmrus=; b=DS/ty1HTeG9xeq5JCyjCoETAO1mUw+dZkJ7CfLHpGGKpEH6cOvAZrYNhna6DvPHbwx ApHE21ypv5098YpfJ2NIJfRznScPwRn3UNc3ws972AMzKSOuB11b4PdQ0GUfsz0S3zeW /78cS/rtB/ItQd7yhaRYiS56eN7mQhaY5XR/Ozzo5BggvYW5UerZA2/OvgN1rjpGf0xr miiiZngPauj3da8XjeDDM0DMc1TFRW0mfcibHr6vSF3vUPulaSqdfqHQw4AbWZ488pVV 79MODPczzpWX8xivDwmtOjyxK04wNA7D1jNG8R0xCt2Ook8IzqLxAhtTHyQc0jKRlKwl qnQA==
X-Received: by with SMTP id n66mr7221848pfi.42.1449085449869; Wed, 02 Dec 2015 11:44:09 -0800 (PST)
Received: from [] ([]) by with ESMTPSA id l20sm5973816pfi.10.2015. (version=TLSv1/SSLv3 cipher=OTHER); Wed, 02 Dec 2015 11:44:08 -0800 (PST)
Content-Type: multipart/alternative; boundary="Apple-Mail-E18D7D4B-25A1-48D0-B561-A62C4238E45D"
Mime-Version: 1.0 (1.0)
From: Fabrice Gautier <>
X-Mailer: iPhone Mail (13A340)
In-Reply-To: <>
Date: Wed, 02 Dec 2015 11:48:47 -0800
Content-Transfer-Encoding: 7bit
Message-Id: <>
References: <> <> <> <> <>
To: Bryan Ford <>
Archived-At: <>
Cc: "" <>
Subject: Re: [TLS] Encrypting record headers: practical for TLS 1.3 after all?
X-Mailman-Version: 2.1.15
Precedence: list
List-Id: "This is the mailing list for the Transport Layer Security working group of the IETF." <>
List-Unsubscribe: <>, <>
List-Archive: <>
List-Post: <>
List-Help: <>
List-Subscribe: <>, <>
X-List-Received-Date: Wed, 02 Dec 2015 19:44:13 -0000

> On Dec 2, 2015, at 01:51, Bryan Ford <> wrote:
>> On 02 Dec 2015, at 00:54, Fabrice Gautier <> wrote:
>>> On Tue, Dec 1, 2015 at 7:27 AM, Bryan A Ford <> wrote:
>>>> On 12/1/15 4:02 AM, Fabrice Gautier wrote:
>>>> 1) What would be the implications of this for DTLS? (Knowing that one difference between TLS and DTLS is the record header)
>>> Good question.  Fortunately my proposal should be fairly easy to adapt
>>> to DTLS, with one small trick. […]
>> Hum.... I wouldn't qualify this as a "fairly simple" solution.
> A reasonable but subjective position, which I think we should further discuss later if/when this (or some) WG actually revisits DTLS. :)

Well, it's objectively several order of magnitude more complex than the current record framing. 

And I certainly hope than TLS 1.3 is designed with DTLS in mind. 

>>>> 2) In some implementations the record framing/parsing and encryption/decryption are down at different layers. Would this proposal make this type of implementation impossible?
>>> Not that I'm aware of, but I might need more information about the
>>> specific layering approaches you're thinking of and how "strongly
>>> enforced" that layering might be.
>> For example:
>>  A TLS library might be logically separated into two main parts:
>> 1) A record parsing block, that just take a stream of bytes as in
>> input (eg: from a socket) and output a series a record.
>> 2) A decrypt function, that take as input full encrypted record and
>> output a decrypted one.
>> There may be various reason to do this: flexibility, clean layering,
>> maintainability, testability, etc...
>> Another reason, maybe performance. For example, a network stack might
>> not want to send partial records to the application to decrypt. Having
>> a simple way for a network stack to implement TLS framing maybe
>> beneficial. Currently it would be fairly simple to implement TLS
>> record parsing in a TCP stack. But with your proposal it seems it
>> would mean the parsing layer would need to get keys and do crypto.
> In my first proposal, with headers encrypted with a stream cipher (or AEAD used as one), I think this kind of layering should still be quite feasible, with the one caveat that the TLS record parsing layer does indeed need to make one new “call” into the crypto-related code (to get the header) in addition to the one it already does (to pass the body and header to the crypto code for body-decryption and integrity-check).  

That is one big caveat. And you description doesn't really match what I have in mind. 

In particular, currently, record framing and decryption doesn't need to be synchronous and there is no particular requirement for which one call the other.

So a TLS record framing implemented in an OS kernel TCP stack would not "call" into the decryption layer in userland. It would just queue data in its socket buffer and only signal to userland that data is available when a full record is available to be decrypted.

So it just wouldn't be practical to do this at all with your scheme.

> And only on the receive path; the send path seems pretty much unaffected.  This doesn’t seem like a big layering problem to me, but again subjective opinions may vary.
> In my second proposal, with headers fully encrypted and integrity-checked along with the body, I think the opportunity for the clean layering you propose comes back and perhaps gets even better: it’s just that the record writing/parsing now happens *inside* rather than outside the encryption boundary.  In other words, their order is reversed: the sender invokes the record-writing code first, then the AEAD encryption code to encrypt everything (header and data) at once; the receiver flow invokes the AEAD decryption code first to decrypt everything,

For my example above, the second proposal requires that the application layer tell the network stack what the expected size of the next record is. 

For some implementation it may be more efficient as the decryption layer (in the application) knows exactly how much data it needs to read from the socket - whereas today you need to read the header first, then the rest. 
But it still doesn't allow the network stack to - on its own - signal to the application when it received enough data ready to be decrypted.

> then invokes the separately-modularized record parsing code on the already fully decrypted and integrity-checked record content.  This seems even cleaner to me than the current approach, where the record parsing code has to do some (very careful!) parsing of the record before it’s been authenticated,

The current header is so simple there is virtually no risk to get the framing wrong, and nothing really bad happen even if you do get it wrong.

> then invoke decryption, then do some more internal parsing on the decrypted AEAD body (e.g., the encrypted content-type within).
> B