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

Fabrice Gautier <> Tue, 01 December 2015 23:55 UTC

Return-Path: <>
Received: from localhost ( []) by (Postfix) with ESMTP id 4CD1F1B2AEF for <>; Tue, 1 Dec 2015 15:55:18 -0800 (PST)
X-Virus-Scanned: amavisd-new at
X-Spam-Flag: NO
X-Spam-Score: -2
X-Spam-Status: No, score=-2 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, SPF_PASS=-0.001] autolearn=ham
Received: from ([]) by localhost ( []) (amavisd-new, port 10024) with ESMTP id nXwFSCDvXsDR for <>; Tue, 1 Dec 2015 15:55:13 -0800 (PST)
Received: from ( [IPv6:2a00:1450:4010:c07::22d]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by (Postfix) with ESMTPS id 98C6E1B2AEC for <>; Tue, 1 Dec 2015 15:55:12 -0800 (PST)
Received: by lffu14 with SMTP id u14so30120817lff.1 for <>; Tue, 01 Dec 2015 15:55:10 -0800 (PST)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;; s=20120113; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :cc:content-type; bh=Ydi+1QB3959gzXFANEHIOGdt91tXqTTWfGoKSuV1ZBs=; b=Mh1ZzW71B8lKrOHFWlZLg9flgydQwWju8A45x4DdWNBdPixZ/bP+Oqpk+e6OuGS69h QR7IOo3Z/x5Kem3EXFOSGE49kAYtNJ7/JcLJwjlYYQC43Rkn/NYy3+ksw8NPcJGTloHk k8SL66WjYbkpbIEzEEFZuGfgh7ZMUVAPL9HcS7IknGbBtwIJfTfRKYAzqTdel8BZ9vvX vUR9LLr1DPlCJedOQV9Ey97dHspETdZ1793UxIX+SK5JUsXr9KgLkG5g5CuPTGD8iWeJ 2b3bIloKaYjTyUGUnH83Q2u9OrsfSuEfdKMi7DukUcmagp50HyuV2RvwUBgE+PCccz/3 Aivg==
X-Received: by with SMTP id b140mr140172lfe.33.1449014110762; Tue, 01 Dec 2015 15:55:10 -0800 (PST)
MIME-Version: 1.0
Received: by with HTTP; Tue, 1 Dec 2015 15:54:51 -0800 (PST)
In-Reply-To: <>
References: <> <> <>
From: Fabrice Gautier <>
Date: Tue, 01 Dec 2015 15:54:51 -0800
Message-ID: <>
To: Bryan A Ford <>
Content-Type: text/plain; charset="UTF-8"
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: Tue, 01 Dec 2015 23:55:18 -0000

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.
> The main issue is that DTLS packets need to contain explicitly
> transmitted sequence numbers rather than implicit sequence numbers,
> because packets can be received out of the order and the receiver needs
> to know which sequence number (and hence which nonce) to use to try to
> decrypt and integrity-check.  But if we encrypt the full DTLS header
> including sequence number, how does the receiver decrypt it without
> knowing the correct nonce to use to decrypt it?  An apparent
> chicken-and-egg problem.
> Fortunately the solution is fairly simple: the receiver simply
> pre-computes and keeps in a small hash table the encrypted sequence
> numbers of all packets with sequence numbers between H-W and H+W, where
> H is the highest sequence number correctly received so far (the horizon)
> and W is the anti-replay window size as specified in of RFC
> 4347, which typically should be 32 or 64 according to the RFC.  The
> receiver can precompute all these encryptions because in my proposal TLS
> headers are encrypted with a stream cipher (or the AEAD operating as a
> stream cipher), so it's just a matter of producing the correct
> cipherstream bytes and XORing them with the uint48 sequence number.
> Whenever the receiver gets a datagram, it looks up the encrypted
> sequence number in the hash table, drops it on the floor if it's not
> present, and if it's present the receiver gets the decrypted sequence
> number from the hash table and uses that in the AEAD decryption and
> integrity-check.  In the low-probability event of a hash-table collision
> (i.e., two uint48 sequence numbers encrypting to the same 48-bit
> ciphertext in a single 129-datagram window), the receiver can
> trial-decrypt with both (or all) sequence numbers in that colliding hash
> table entry.  Or the receiver can keep it even simpler and just drop all
> but one colliding entry, introducing a pretty low probability of
> introducing occasional "false packet drops."
> The hash table is pretty trivial to maintain efficiently as well: e.g.,
> whenever the horizon H moves forward by delta D, remove the first D
> entries from the current window and precompute another D encrypted
> sequence numbers (where D will most often be 1).  In the simple design
> that doesn't bother dealing with hash table collisions (e.g., that
> allows each hash table entry to contain only one value), perhaps don't
> even bother clearing/removing old entries; just gradually overwrite them
> with new ones as H moves forward.

Hum.... I wouldn't qualify this as a "fairly simple" solution.

>> 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.

> But in the version of my proposal
> that operates the "normal" AEAD as a stream cipher for header
> encryption/decryption purposes, it doesn't seem like any change would be
> needed to the standard AEAD encryption/decryption interface.  It should
> even be fine if the AEAD was implemented as a separate hardware module
> that takes the standard AEAD interface inputs and produces the standard
> AEAD outputs; as long as it supports the standard AEAD API it should be
> perfectly usable in the design I proposed.
> The one potential issue I can think of if a particular, restricted API
> forces the caller to commit at key-setup time to either "AEAD encryption
> mode" or "AEAD decryption mode", and makes it difficult or impossible to
> switch back and forth.  In that case in my proposal as it stands the
> receiver TLS implementation might need to set up and maintain two
> hardware contexts, one for AEAD decryption (for the payloads), the other
> for AEAD encryption (for stream cipher header decryption), both using
> the symmetric key.  This still doesn't seem all that problematic to me,
> though, and I don't even know of any particular APIs offhand that
> present this particular issue.

This is all good, except that your proposal requires that the record
parsing layers has access to some AEAD API. So far it didn't need an
AEAD API at all.

> Cheers
> Bryan