Re: [TLS] Prototype of TLS 1.3 records, padding, and optional headerless records

Bryan Ford <brynosaurus@gmail.com> Tue, 23 February 2016 10:45 UTC

Return-Path: <brynosaurus@gmail.com>
X-Original-To: tls@ietfa.amsl.com
Delivered-To: tls@ietfa.amsl.com
Received: from localhost (ietfa.amsl.com [127.0.0.1]) by ietfa.amsl.com (Postfix) with ESMTP id 2A8EE1B4152 for <tls@ietfa.amsl.com>; Tue, 23 Feb 2016 02:45:12 -0800 (PST)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: -0.101
X-Spam-Level:
X-Spam-Status: No, score=-0.101 tagged_above=-999 required=5 tests=[BAYES_40=-0.001, 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 mail.ietf.org ([4.31.198.44]) by localhost (ietfa.amsl.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id qMpoYTSwRugd for <tls@ietfa.amsl.com>; Tue, 23 Feb 2016 02:45:08 -0800 (PST)
Received: from mail-pa0-x22c.google.com (mail-pa0-x22c.google.com [IPv6:2607:f8b0:400e:c03::22c]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by ietfa.amsl.com (Postfix) with ESMTPS id 8A9701B4020 for <TLS@ietf.org>; Tue, 23 Feb 2016 02:45:05 -0800 (PST)
Received: by mail-pa0-x22c.google.com with SMTP id fy10so108356917pac.1 for <TLS@ietf.org>; Tue, 23 Feb 2016 02:45:05 -0800 (PST)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:content-type:message-id:mime-version:subject:date:references :to:in-reply-to; bh=4asjqKncze7V/Tse40DE8EXKAnFRmT79UAvzn2/Suak=; b=MkXrlzkWnmZNLH2d9nfUNgDVhrZSHr/YtsJlJAyKvj3XGTabNoDO7Dst9jaynZrlZf 7UfQ9lD7pSq5X7HRJvwpvpWTUFci5zmcoBnWTvTrpR7ZPlcNJcL2RdK7KaDo44WRYDn2 CdbIOMIcoIW1SmWqnYn5CMNoodq7Bsy2RejNaVWjrYD1HcSHWxQKOzx163yUen1P2ck8 lmCkrCCjJjIY7Q6ohYEOOETyNt0iRZEmpxTk6LIoA9IsCQPAzvYdQun+rbAj0fehHjrk IE6FylrN3G3qiCS0ptkUjQlNFVXzoldH9b5F3Au54AZFvGPg312iZqmCVsUzC0ZmaTUF N5CQ==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:content-type:message-id:mime-version :subject:date:references:to:in-reply-to; bh=4asjqKncze7V/Tse40DE8EXKAnFRmT79UAvzn2/Suak=; b=YoqQMDwn2Fe31djrV9BQLFAYEZpzBkxAHIcP5BxVFlifPnhJrN87UC6O+EW9EjvSeV N2itHo+hqS85DZ6A0KSRD5STdKZE4p8SQq/YtSN7pvWZ5LkM3Wj02gf+hVxdExUUBizm u81BIWoHXD2OEam0pcCWGj6BUQ6P/Wc07hgIET56K012dGAq4+9ylp435lQda3li7kGW 2X8Ys9bif5R2daCZi8VtFXzMspGNM2ny7g2fZ660w4NRPvCzzqeQ9yN7oibLwZHm2e4A 1UQlvmg4ysqTjY6nhj+9/KyoSmrBvAUBGdAuiPfLLvZS3ZmYyrE/cJ3L5mV8HOsDHshz edZA==
X-Gm-Message-State: AG10YOQtYAXESzj1q9fTsMeYThgMBdCmILvHGBWZhLVm/smf1N0DJoE902V6EBoVOJfEcg==
X-Received: by 10.67.23.161 with SMTP id ib1mr43453133pad.156.1456224305168; Tue, 23 Feb 2016 02:45:05 -0800 (PST)
Received: from [172.25.0.204] (rrcs-67-52-140-5.west.biz.rr.com. [67.52.140.5]) by smtp.gmail.com with ESMTPSA id c68sm26475526pfj.41.2016.02.23.02.45.02 for <TLS@ietf.org> (version=TLS1 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 23 Feb 2016 02:45:02 -0800 (PST)
From: Bryan Ford <brynosaurus@gmail.com>
Content-Type: multipart/signed; boundary="Apple-Mail=_CF36275F-F4EA-48FD-975E-77410095E1FF"; protocol="application/pkcs7-signature"; micalg="sha1"
Message-Id: <2771EB48-C7CD-4454-91EF-480F4FA1EBE7@gmail.com>
Mime-Version: 1.0 (Mac OS X Mail 9.2 \(3112\))
Date: Tue, 23 Feb 2016 02:45:01 -0800
References: <566BF6F4.7050100@gmail.com>
To: "tls@ietf.org" <TLS@ietf.org>
In-Reply-To: <566BF6F4.7050100@gmail.com>
X-Mailer: Apple Mail (2.3112)
Archived-At: <http://mailarchive.ietf.org/arch/msg/tls/_p4jzi7RXAJ0hk5-v8x8AO6_BTU>
Subject: Re: [TLS] Prototype of TLS 1.3 records, padding, and optional headerless records
X-BeenThere: tls@ietf.org
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." <tls.ietf.org>
List-Unsubscribe: <https://www.ietf.org/mailman/options/tls>, <mailto:tls-request@ietf.org?subject=unsubscribe>
List-Archive: <https://mailarchive.ietf.org/arch/browse/tls/>
List-Post: <mailto:tls@ietf.org>
List-Help: <mailto:tls-request@ietf.org?subject=help>
List-Subscribe: <https://www.ietf.org/mailman/listinfo/tls>, <mailto:tls-request@ietf.org?subject=subscribe>
X-List-Received-Date: Tue, 23 Feb 2016 10:45:12 -0000

In followup to my talk in the TRON workshop, I have opened the following Issue proposing to make unencrypted headers optional, as per my earlier E-mails on Dec 1 and 12:

	https://github.com/tlswg/tls13-spec/issues/422
	Add encrypted NextRecordLength field to make next record's unencrypted header optional

The precise (1- or 2-byte) encoding I leave for further discussion.

Thanks
Bryan

> On Dec 12, 2015, at 2:29 AM, Bryan A Ford <brynosaurus@gmail.com> wrote:
> 
> Since a lot of the skepticism toward my encrypted-headers proposal
> constituted worries whether the benefits are worth the implementation
> cost/complexity, I decided to implement it and find out what that cost
> and complexity actually is.  See this github repo:
> 
> 	https://github.com/bford/nss
> 
> Here you'll find a snapshot of Mozilla NSS/NSPR, with three branches:
> (a) current baseline version supporting only TLS 1.2 records; (b) a
> version that adds support for the currently-specified TLS 1.3 record
> format with the encrypted content-type trailer and padding within the
> AEAD; and (c) a further extension to support optional "headerless"
> records.  This doesn't implement all the other new stuff in TLS 1.3 such
> as negotiation, 0-RTT, etc. - only the record-layer changes.
> 
> ---
> Observations from implementing TLS 1.3 records:
> 
> The baseline...master diff (https://github.com/bford/nss/pull/1/files)
> represents the changes that appear needed to get from TLS 1.2 records to
> TLS 1.3 record format, with padding of records to a constant size for
> traffic analysis protection.  I set the fixed padded record length
> (TLS13_PAD_FRAGMENT_LENGTH) to 256 bytes "just because", but change it
> to whatever you like; I don't have any fish to fry regarding the
> specific "best" value.  512 and 1024 also seem like reasonable choices,
> with obvious tradeoffs between wasted bytes padding small messages
> versus the bandwidth and processing overheads of fewer bytes per record.
> 
> Measuring implementation complexity simplistically by line count, this
> diff constitutes +92-14=78 lines (92 added, 14 removed) - nothing too
> serious.  Subjectively, the main implementation came from adding the
> 1-byte internal content-type trailer in the first place, which means
> having to copy the input cleartext into the write buffer in order to
> fiddle with it before passing it to the AEAD encryptor.  Thus, because
> of this 1-byte content-type trailer (even with no padding), we can no
> longer just encrypt directly from the caller-provided input into the
> ciphertext buffer but have to copy the cleartext first, unless the AEAD
> API supports scatter/gather (which NSS's doesn't and I expect most
> probably won't).
> 
> This doesn't seem like a big problem to me and I definitely consider the
> benefits of the encrypted content type and record padding to be worth
> this minor cost.  And in practice I doubt it'll cause any actual
> noticeable performance degradation because a
> copy-A-to-B-then-encrypt-in-place-at-B is going to have a pretty similar
> cache footprint as an encrypt-from-A-to-B.
> 
> TLS 1.3 also already changes the way the pseudo-header is calculated for
> MAC purposes; I didn't yet fully implement those changes, but did
> already need to move the pseudo-header calculation on the send side
> until a bit later when the length of the ciphertext is known.
> 
> ---
> Headerless records extension:
> 
> The other pull request (https://github.com/bford/nss/pull/2/files)
> represents the further delta needed to implement a further simplified
> version of my last "encrypted headers" proposal, which in this
> incarnation becomes "headerless records".  Since TLS 1.3 is already
> adding a 1-byte mandatory encrypted trailer within each record (the
> encrypted content-type), I simply extended this to a 3-byte trailer, in
> which the first two bytes indicate:
> 
> - If zero, the next record (following this one) has the usual 5-byte TLS
> header and its length is defined by that header as usual.
> - If nonzero, the next record has *no* TLS header at all, and its length
> is defined by this value.
> 
> By combining the "next-record-length" into the encrypted trailer that
> TLS 1.3 is adding anyway, the changes required are pretty minimal.  By
> my count, this is a delta of +40-8=32 lines, which at least to me seems
> pretty insignificant in terms of implementation complexity.  And
> implementations could be even simpler by not implementing the send-side
> logic at all and simply setting all next-record-length fields in the
> trailers to zero, attaching headers to all records as before.  The only
> minor point of "implementation pain" is the need to add the appropriate
> inter-record state variables (writeNextLength and readNextLength), but
> the handling of these are not fundamentally any different from the state
> needed to keep track of sequence numbers across records for example.
> 
> Making headerless records optional, selected by the trailer in the prior
> record as defined above, offers several nice benefits:
> 
> - It address the concerns that have been raised (though unsubstantiated
> so far with any concrete evidence) about breaking middleboxes that want
> to parse traditional TLS record streams.  TLS implementations that are
> paranoid to this degree about breaking middleboxes can simply always set
> the next-header-length field in the trailer to 0 and send cleartext
> record headers for every TLS record just as before.
> 
> - We don't need to do anything special to handle the "first record"
> case: i.e., we neither need to specify a standard "first record length"
> nor add a first-record-length field to one of the negotiation packets.
> Instead, the first AEAD-encrypted record is simply transmitted with a
> 5-byte header as usual, but the sender can omit the headers from
> subsequent records if it chooses to.
> 
> - A TLS 1.3 implementation that doesn't want to bother "predicting" or
> "committing to" a next-record-length beyond a SSL_Write() boundary can
> simply set the next-record-length field to zero in the last record of
> the current write, so the first record in the next SSL_Write() will
> including a header determining its size as before.  This isn't ideal in
> terms of traffic analysis protection, but it's an implementation option.
> 
> - FWIW, when the sender transmits headerless records, the encoding saves
> 2 bytes per record with respect to TLS 1.2 (saving the 5-byte cleartext
> header but adding the 3-byte encrypted trailer).
> 
> ---
> Implications on padded record transmission:
> 
> Finally, while implementing this extension I realized a further general
> benefit of headerless transmission: it can make the use of padding for
> traffic analysis protection more bandwidth-efficient.
> 
> With cleartext headers, to achieve the traffic analysis benefits of
> padding we must ensure that every transmitted record has *exactly* the
> same ciphertext length, since any variation will produce a readily
> fingerprintable pattern in cleartext.  This creates tradeoffs, as noted
> above.  Padding to a smaller fixed size (e.g., 256 bytes) adds less
> bandwidth overhead to small messages such as typical HTTP requests but
> incurs the cost of a MAC tag, nonce, TLS headers/trailers etc once every
> 256 bytes - for AES-GCM this is about an 11% bandwidth overhead with
> 256-byte records.  Padding to a larger fixed size (e.g., 1024) reduces
> the bandwidth overhead for bulk data transmission such as large HTTP
> responses (e.g., to about 3% overhead with 1024-byte records), at a cost
> of adding a lot of bandwidth overhead to tiny HTTP requests or
> status-indication responses, which are also common.
> 
> With headerless records, in contrast, we can pick a relatively small
> ciphertext length padding granularity (e.g., 256 bytes), but then the
> sender can transmit records whose sizes are any *multiple* of this
> granularity, because N consecutive 256-byte ciphertexts are now
> cryptographically indistinguishable from a single N*256-byte ciphertext.
> Thus, we get the bandwidth-efficiency benefits of small records by
> avoiding the need to add too much padding to small messages, plus the
> bandwidth-efficiency benefits of larger records for bulk transmission.
> For example, we can send a large message mostly consisting of
> ~16384-byte records, each containing only one MAC tag and internal TLS
> 1.3 trailer (though an eavesdropper won't know that), reducing the
> bandwidth overhead in the AES-GCM case from 11% to 0.2%.
> 
> There are two minor caveats to this:
> 
> - In the specific case of AES-GCM, it looks like TLS 1.2 uses AES-GCM
> with explicitly transmitted nonces, which are clearly distinguishable
> from random values and hence will break the above benefits.  The
> solution is simple, however: simply make TLS 1.3 use AES-GCM (and other
> AEAD schemes) without explicit nonces.  These nonces can be calculated
> implicitly by sender and receiver just as easily without explicit
> transmission, and all the necessary integrity-checking happens via the
> "additional_data" pseudo-header anyway.  (In fact perhaps TLS 1.3
> already eliminates the explicit nonce - I don't see any mention of it in
> the new record spec anyway, the only question is whether it's still in
> the AES-GCM-specific specs, which I haven't looked at closely and don't
> know if they'll be updated wrt TLS 1.3 or not.)
> 
> - Even if N 256-byte ciphertexts in a TLS 1.3 stream are
> cryptographically indistinguishable from one N*256-byte ciphertext, if
> the TLS sender implementation transmits these in a single OS write(),
> the OS's TCP stack may (or may not, depending on circumstances) still
> reveal this difference by segmenting transmitted TCP segments
> differently.  There are several obvious solutions to this, however:
> 
> 	(1) The TLS implementation could prepare the N*256-byte ciphertext but
> then transmit it using N separate 256-byte write() calls to the
> underlying TCP stack.  This might (again depending on the TCP stack)
> increase the TCP-level overhead by sending many smaller-than-necessary
> TCP segments, but is a fully OS-independent solution, and we still save
> the TLS-level bandwidth overhead (one MAC tag etc rather than N).
> 
> 	(2) Better, at least on Linux systems, the TLS implementation could
> simply enable the TCP_CORK socket option, causing the kernel to delay
> the transmission of incomplete (less-than-MTU-sized) TCP segments
> slightly in hopes of "filling" them.  This way, the TLS sender will
> always produce continuous streams of MTU-sized TCP segments for all
> "bursts" of transmission of any number of TLS records.  The downside is
> that the kernel-imposed delay can add a bit of latency (I understand
> around 200ms) to the transmission of the very last, incomplete segment
> in a burst, thus perhaps adding up to 200ms to the total
> request/response latency of a round-trip interactive exchange.
> 
> 	(3) Still better, again on Linux systems, the TLS implementation could
> send records using send() instead of write(), and set the MSG_MORE flag
> on all records except for the last record just before the connection
> goes idle (no more data to transmit).  Figuring  out when a connection
> is "going idle" may require some heuristics or hints from the
> application, but can ensure that bursts are transmitted as a fully
> uniform series of MTU-size segments without incurring any added delay at
> the end.
> 
> ---
> OK, congratulations and thanks to anyone who persisted through all that.
> I hope this will help understand the implementation complexity and
> tradeoffs both of the currently-specified TLS 1.3 record layer and the
> proposed headerless records features.  Comments?
> 
> Thanks
> Bryan
>