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

Bryan A Ford <> Thu, 03 December 2015 09:51 UTC

Return-Path: <>
Received: from localhost ( []) by (Postfix) with ESMTP id 68F051A1BCC for <>; Thu, 3 Dec 2015 01:51:26 -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 4hOD4CFkon4G for <>; Thu, 3 Dec 2015 01:51:24 -0800 (PST)
Received: from ( [IPv6:2a00:1450:400c:c09::22f]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by (Postfix) with ESMTPS id A89981A1B95 for <>; Thu, 3 Dec 2015 01:51:23 -0800 (PST)
Received: by wmvv187 with SMTP id v187so18355400wmv.1 for <>; Thu, 03 Dec 2015 01:51:22 -0800 (PST)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;; s=20120113; h=subject:to:references:cc:from:message-id:date:user-agent :mime-version:in-reply-to:content-type; bh=zK9+YFrtarjYbPKIS1nO5r3HbZpD28k162cafu6S1PA=; b=Iz6KsMKlRYivEnDNv79q76iobHM+PaG9Ee4EVVjWJ14C7D7VmhiMFBFIFlcPbw0K39 K3ZFCrN3O0lptW8+0dyubcv50OPhifbIsc357ubSUbAKJn5jRTM1y/Y7CeInZghsK+zb 7QucXSe86hc4uw6oXOhmRI9NTqLdtJTwbuv9iKgv+JjuO4lu3/0WsnruxxpwrCGk/jlN jzHhoF+VQSy6LCzvUc2vNHc1EcigKJSJwhhP7QQa/qmFWZdt559yX8GKWeB3PaW5ljWa GciasggMDD8lEwHSnnppOOLnshgMDfYJTVtBRFhVFmGhGzqtdZZwBhW0dQ4OctS2GhaB i6+Q==
X-Received: by with SMTP id v131mr51473664wma.63.1449136282316; Thu, 03 Dec 2015 01:51:22 -0800 (PST)
Received: from ( []) by with ESMTPSA id an7sm6712908wjc.44.2015. (version=TLSv1/SSLv3 cipher=OTHER); Thu, 03 Dec 2015 01:51:20 -0800 (PST)
To: "GUBALLA, JENS (JENS)" <>, Fabrice Gautier <>
References: <> <> <> <>
From: Bryan A Ford <>
X-Enigmail-Draft-Status: N1110
Message-ID: <>
Date: Thu, 03 Dec 2015 10:51:24 +0100
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:38.0) Gecko/20100101 Thunderbird/38.3.0
MIME-Version: 1.0
In-Reply-To: <>
Content-Type: multipart/signed; protocol="application/pkcs7-signature"; micalg="sha-256"; boundary="------------ms040303040002020403080607"
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: Thu, 03 Dec 2015 09:51:26 -0000

Hi Jens,

On 12/2/15 11:47 AM, GUBALLA, JENS (JENS) wrote:
>> 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.
> [JG] In case there is a packet loss of at least W subsequent DTLS records: 
> How can the receiver then ever adjust its hash table? Wouldn't that mean 
> that no records at all would be accepted anymore?

Excellent question - I had intended to discuss that in my original post
but in the end forgot to include it.

Indeed, with this approach as it stands, if every packet within a full
window of W consecutive packets fails to reach the receiver, then the
receiver has no way to resynchronize and the connection will simply
fail.  In congestion-controlled protocols like TCP (or DCCP) that do
exponential backoff when they detect many consecutive losses, the
protocol may be more likely simply to hard-timeout than to reach the
W-packet resynchronization limit.  But admittedly many UDP-based
protocols aren't (or are rather weakly) congestion-controlled, so this
may be more of a problem for them.  It's probably the case that the
"forward-looking window" should be allowed to have a different value
from the "backward-looking window", and perhaps the "forward-looking
window" should depend on RTT (e.g., measured maximum packets-in-flight).

However, one way to eliminate this risk of permanent desynchronization,
at the cost of a bit more complexity in the receiver implementation
(though this needn't affect the protocol spec at all) is for the
receiver's "forward-looking window" to consist not of W consecutive
sequence numbers but a sparse set of sequence numbers at
exponentially-increasing distances.  For example, if H is the current
highest sequence number, include in the forward-looking cache the
encrypted sequence numbers of the sequence number of the next multiple
of 2^1 beyond H, the next multiple of 2^2, etc., for as many multiples
of powers-of-two to get sufficiently far out in the sequence number
space where we're convinced there's no realistic chance of a run of
total or near-total packet loss unless it really means the connection is
dead anyway. :)

Again, these are all considerations that need not affect the protocol
but could be tuned by implementations (perhaps with some recommendations
in the protocol spec).

But regardless, all of this is just to make the case that header
encryption is in principle just as feasible in DTLS as in TLS, and using
fairly similar techniques; right now I think we should keep the main
focus on whether to do it (at least) in TLS, for which is seems pretty
easy to do it in at least two different ways I've proposed.