Internet-Draft | cTLS 1.3 | March 2022 |
Rescorla, et al. | Expires 8 September 2022 | [Page] |
This document specifies a "compact" version of TLS 1.3. It is isomorphic to TLS 1.3 but saves space by trimming obsolete material, tighter encoding, a template-based specialization technique, and alternative cryptographic techniques. cTLS is not directly interoperable with TLS 1.3, but it should eventually be possible for a cTLS/TLS 1.3 server to exist and successfully interoperate.¶
This Internet-Draft is submitted in full conformance with the provisions of BCP 78 and BCP 79.¶
Internet-Drafts are working documents of the Internet Engineering Task Force (IETF). Note that other groups may also distribute working documents as Internet-Drafts. The list of current Internet-Drafts is at https://datatracker.ietf.org/drafts/current/.¶
Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress."¶
This Internet-Draft will expire on 8 September 2022.¶
Copyright (c) 2022 IETF Trust and the persons identified as the document authors. All rights reserved.¶
This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Revised BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Revised BSD License.¶
DISCLAIMER: This is a work-in-progress draft of cTLS and has not yet seen significant security analysis, so could contain major errors. It should not be used as a basis for building production systems.¶
This document specifies a "compact" version of TLS 1.3 [RFC8446]. It is isomorphic to TLS 1.3 but designed to take up minimal bandwidth. The space reduction is achieved by five basic techniques:¶
For the common (EC)DHE handshake with pre-established certificates, cTLS achieves an overhead of 45 bytes over the minimum required by the cryptovariables. For a PSK handshake, the overhead is 21 bytes. Annotated handshake transcripts for these cases can be found in Appendix A.¶
Because cTLS is semantically equivalent to TLS, it can be viewed either as a related protocol or as a compression mechanism. Specifically, it can be implemented by a layer between the TLS handshake state machine and the record layer.¶
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.¶
Structure definitions listed below override TLS 1.3 definitions; any PDU not internally defined is taken from TLS 1.3.¶
A significant transmission overhead in TLS 1.3 is contributed to by two factors, : - the negotiation of algorithm parameters, and extensions, as well as - the exchange of certificates.¶
TLS 1.3 supports different credential types and modes that are impacted differently by a compression scheme. For example, TLS supports certificate-based authentication, raw public key-based authentication as well as pre-shared key (PSK)-based authentication. PSK-based authentication can be used with externally configured PSKs or with PSKs established through tickets.¶
The basic idea of template-based specialization is that we start with the basic TLS 1.3 handshake, which is fully general and then remove degrees of freedom, eliding parts of the handshake which are used to express those degrees of freedom. For example, if we only support one version of TLS, then it is not necessary to have version negotiation and the supported_versions extension can be omitted.¶
Importantly, this process is performed only for the wire encoding but not for the handshake transcript. The result is that the transcript for a specialized cTLS handshake is the same as the transcript for a TLS 1.3 handshake with the same features used.¶
One way of thinking of this is as if specialization is a stateful compression layer between the handshake and the record layer:¶
+---------------+---------------+---------------+ | Handshake | Application | Alert | +---------------+---------------+---------------+ +---------+ | cTLS Compression Layer |<---| Profile | +---------------+---------------+---------------+ +---------+ | cTLS Record Layer / Application | +---------------+---------------+---------------+¶
By assuming that out-of-band agreements took place already prior to the start of the cTLS protocol exchange, the amount of data exchanged can be radically reduced. Because different clients may use different compression templates and because multiple compression templates may be available for use in different deployment environments, a client needs to inform the server about the profile it is planning to use. The profile field in the ClientHello serves this purpose.¶
Although the template-based specialization mechanisms described here are general, we also include specific mechanism for certificate-based exchanges because those are where the most complexity and size reduction can be obtained. Most of the other exchanges in TLS 1.3 are highly optimized and do not require compression to be used.¶
The compression profile defining the use of algorithms, algorithm parameters, and extensions is specified via a JSON dictionary.¶
For example, the following specialization describes a protocol with a single fixed version (TLS 1.3) and a single fixed cipher suite (TLS_AES_128_GCM_SHA256). On the wire, ClientHello.cipher_suites, ServerHello.cipher_suites, and the supported_versions extensions in the ClientHello and ServerHello would be omitted.¶
{ "version" : 772, "cipherSuite" : "TLS_AES_128_GCM_SHA256" }¶
The following elements are defined:¶
[[Open Issue: Karthik Bhargavan suggested the idea of hashing ephemeral public keys and to use the result (truncated to 32 bytes) as random values. Such a change would require a security analysis. ]]¶
28 // Extensions.length 33 26 // KeyShare 0024 // client_shares.length 001d // KeyShareEntry.group 0020 a690...af948 // KeyShareEntry.key_exchange¶
is compressed down to (assuming the KeyShare group has been pre-agreed)¶
0020 a690...af948 // KeyShareEntry.key_exchange¶
[[OPEN ISSUE: How short should we allow this to be? TLS 1.3 uses the native hash and TLS 1.2 used 12 bytes. More analysis is needed to know the minimum safe Finished size. See [RFC8446]; Section E.1 for more on this, as well as https://mailarchive.ietf.org/arch/msg/tls/TugB5ddJu3nYg7chcyeIyUqWSbA.]]¶
To be compatible with the specializations described in this section, a TLS stack needs to provide the following features:¶
Extensions used in the ClientHello, ServerHello, EncryptedExtensions, and CertificateRequest messages can be "predefined" in a compression profile, so that they do not have to be sent on the wire. A predefined extensions object is a dictionary whose keys are extension names specified in the TLS ExtensionTypeRegistry specified in [RFC8446]. The corresponding value is a hex-encoded value for the ExtensionData field of the extension.¶
When compressing a handshake message, the sender compares the extensions in the message being compressed to the predefined extensions object, applying the following rules:¶
If there is an entry:¶
When decompressing a handshake message the receiver reconstitutes the original extensions list using the predefined extensions:¶
Note that the "version", "dhGroup", and "signatureAlgorithm" fields in the compression profile are specific instances of this algorithm for the corresponding extensions.¶
[[OPEN ISSUE: Are there other extensions that would benefit from special treatment, as opposed to hex values.]]¶
Certificates are a major contributor to the size of a TLS handshake. In order to avoid this overhead when the parties to a handshake have already exchanged certificates, a compression profile can specify a dictionary of "known certificates" that effectively acts as a compression dictionary on certificates.¶
A known certificates object is a JSON dictionary whose keys are strings containing hex-encoded compressed values. The corresponding values are hex-encoded strings representing the uncompressed values. For example:¶
{ "00": "3082...", "01": "3082...", }¶
When compressing a Certificate message, the sender examines the cert_data field of each CertificateEntry. If the cert_data matches a value in the known certificates object, then the sender replaces the cert_data with the corresponding key. Decompression works the opposite way, replacing keys with values.¶
Note that in this scheme, there is no signaling on the wire for whether a given cert_data value is compressed or uncompressed. Known certificates objects SHOULD be constructed in such a way as to avoid a uncompressed object being mistaken for compressed one and erroneously decompressed. For X.509, it is sufficient for the first byte of the compressed value (key) to have a value other than 0x30, since every X.509 certificate starts with this byte.¶
The only cTLS records that are sent in plaintext are handshake records
(ClientHello and ServerHello/HRR) and alerts. cTLS alerts are the same
as TLS alerts and use the same content types. For handshake records,
we set the content_type
field to a fixed cTLS-specific value to
distinguish cTLS plaintext records from encrypted records, TLS/DTLS
records, and other protocols using the same 5-tuple.¶
struct { ContentType content_type = ctls_handshake; opaque fragment<0..2^16-1>; } CTLSPlaintext;¶
[[OPEN ISSUE: The profile_id is needed in the ClientHello to inform the server what compression profile to use. For a ServerHello this field is not required. Should we make this field optional?]]¶
Encrypted records use DTLS [I-D.draft-ietf-tls-dtls] 1.3 record framing, comprising a configuration octet followed by optional connection ID, sequence number, and length fields. The encryption process and additional data are also as described in DTLS.¶
0 1 2 3 4 5 6 7 +-+-+-+-+-+-+-+-+ |0|0|1|C|S|L|E E| +-+-+-+-+-+-+-+-+ | Connection ID | Legend: | (if any, | / length as / C - Connection ID (CID) present | negotiated) | S - Sequence number length +-+-+-+-+-+-+-+-+ L - Length present | 8 or 16 bit | E - Epoch |Sequence Number| | (if present) | +-+-+-+-+-+-+-+-+ | 16 bit Length | | (if present) | +-+-+-+-+-+-+-+-+ struct { opaque unified_hdr[variable]; opaque encrypted_record[length]; } CTLSCiphertext;¶
The presence and size of the connection ID field is negotiated as in DTLS.¶
As with DTLS, the length field MAY be omitted by clearing the L bit, which means that the record consumes the entire rest of the data in the lower level transport. In this case it is not possible to have multiple DTLSCiphertext format records without length fields in the same datagram. In stream-oriented transports (e.g., TCP), the length field MUST be present. For use over other transports length information may be inferred from the underlying layer.¶
Normal DTLS does not provide a mechanism for suppressing the sequence number field entirely. When a reliable, ordered transport (e.g., TCP) is in use, the S bit in the configuration octet MUST be cleared and the sequence number MUST be omitted. When an unreliable transport is in use, the S bit has its usual meaning and the sequence number MUST be included.¶
The cTLS handshake framing is same as the TLS 1.3 handshake framing, except for two changes:¶
struct { HandshakeType msg_type; /* handshake type */ select (Handshake.msg_type) { case client_hello: ClientHello; case server_hello: ServerHello; case hello_retry_request: HelloRetryRequest; case end_of_early_data: EndOfEarlyData; case encrypted_extensions: EncryptedExtensions; case certificate_request: CertificateRequest; case certificate: Certificate; case certificate_verify: CertificateVerify; case finished: Finished; case new_session_ticket: NewSessionTicket; case key_update: KeyUpdate; }; } Handshake;¶
In general, we retain the basic structure of each individual TLS handshake message. However, the following handshake messages have been modified for space reduction and cleaned up to remove pre-TLS 1.3 baggage.¶
The cTLS ClientHello is defined as follows.¶
opaque Random[RandomLength]; // variable length struct { opaque profile_id<0..2^8-1>; Random random; CipherSuite cipher_suites<1..2^16-1>; Extension extensions<1..2^16-1>; } ClientHello;¶
The client uses the profile_id
field to inform the server
about the compression profile being used (see
Section 2.1). This field MUST be set to
a zero-length value and only if no compression profile is used. Non zero-length
values are agreed out of band between the client and server,
as part of the specification of the compression profile.¶
We redefine ServerHello in the following way.¶
struct { Random random; CipherSuite cipher_suite; Extension extensions<1..2^16-1>; } ServerHello;¶
The HelloRetryRequest has the following format.¶
struct { CipherSuite cipher_suite; Extension extensions<2..2^16-1>; } HelloRetryRequest;¶
The HelloRetryRequest is the same as the ServerHello above but without the unnecessary sentinel Random value.¶
This section provides some example specializations.¶
For this example we use TLS 1.3 only with AES_GCM, X25519, ALPN h2, short random values, and everything else is ordinary TLS 1.3.¶
{ "profile" : 1, "version" : 772, "random": 16, "cipherSuite" : "TLS_AES_128_GCM_SHA256", "dhGroup": "X25519", "clientHelloExtensions": { "named_groups": 29, "application_layer_protocol_negotiation" : "030016832", "..." : null } }¶
Version 772 corresponds to the hex representation 0x0304, named group "29" (0x001D) represents X25519.¶
[[OPEN ISSUE: Should we have a registry of well-known profiles?]]¶
WARNING: This document is effectively brand new and has seen no analysis. The idea here is that cTLS is isomorphic to TLS 1.3, and therefore should provide equivalent security guarantees.¶
The use of key ids is a new feature introduced in this document, which requires some analysis, especially as it looks like a potential source of identity misbinding. This is, however, entirely separable from the rest of the specification.¶
Transcript expansion also needs some analysis and we need to determine whether we need an extension to indicate that cTLS is in use and with which profile.¶
This document requests that a code point be allocated from the "TLS ContentType registry. This value must be in the range 0-31 (inclusive). The row to be added in the registry has the following form:¶
Value | Description | DTLS-OK | Reference |
---|---|---|---|
TBD | ctls | Y | RFCXXXX |
TBD | ctls_handshake | Y | RFCXXXX |
[[ RFC EDITOR: Please replace the value TBD with the value assigned by IANA, and the value XXXX to the RFC number assigned for this document. ]]¶
[[OPEN ISSUE: Should we require standards action for all profile IDs that would fit in 2 octets.]]¶
This document requests that IANA open a new registry entitled "cTLS Template Keys", on the Transport Layer Security (TLS) Parameters page, with a "Specification Required" registration policy and the following initial contents:¶
Key | JSON Type | Reference |
---|---|---|
profile | number | (This document) |
version | number | (This document) |
cipherSuite | string | (This document) |
dhGroup | string | (This document) |
signatureAlgorithm | string | (This document) |
random | number | (This document) |
mutualAuth | true/false | (This document) |
extension_order | object | (This document) |
clientHelloExtensions | object | (This document) |
serverHelloExtensions | object | (This document) |
encryptedExtensions | object | (This document) |
certRequestExtensions | object | (This document) |
knownCertificates | object | (This document) |
finishedSize | number | (This document) |
optional | object | (This document) |
The follow exchange illustrates a complete cTLS-based exchange supporting mutual authentication using certificates. The digital signatures use ECDSA with SHA256 and NIST P256r1. The ephemeral Diffie-Hellman uses the FX25519 curve and the exchange negotiates TLS-AES-128-CCM8-SHA256. The certificates are exchanged using certificate identifiers.¶
The resulting byte counts are as follows:¶
ECDHE ------------------ TLS CTLS Overhead --- ---- -------- ClientHello 132 36 4 ServerHello 90 36 4 ServerFlight 478 80 7 ClientFlight 458 80 7 ================================== Total 1158 232 22¶
The following compression profile was used in this example:¶
{ "profile": 1, "version": 772, "cipherSuite": "TLS_AES_128_CCM_8_SHA256", "dhGroup": "X25519", "signatureAlgorithm": "ecdsa_secp256r1_sha256", "finishedSize": 8, "clientHelloExtensions": { "server_name": "000e00000b6578616d706c652e636f6d", }, "certificateRequestExtensions": { "certificate_request_context": 0, "signature_algorithms": "00020403" }, "mutualAuth": true, "extension-order": { "clientHelloExtensions": [ "key_share" ], "ServerHelloExtensions": [ "key_share" ], }, "knownCertificates": { "61": "3082...", "62": "3082...", "63": "...", "64": "...", ... } }¶
ClientHello: 36 bytes = DH(32) + Overhead(4)¶
01 // ClientHello 01 // Profile ID 0020 a690...af948 // KeyShareEntry.key_exchange¶
ServerHello: 36 = DH(32) + Overhead(4)¶
02 // ServerHello 26 // Extensions.length 0020 9fbc...0f49 // KeyShareEntry.key_exchange¶
Server Flight: 80 = SIG(64) + MAC(8) + CERTID(1) + Overhead(7)¶
The EncryptedExtensions, and the CertificateRequest messages are omitted because they are empty.¶
0b // Certificate 03 // CertificateList 01 // CertData.length 61 // CertData = 'a' 0f // CertificateVerify 4064 // Signature.length 3045...10ce // Signature 14 // Finished bfc9d66715bb2b04 // VerifyData¶
Client Flight: 80 bytes = SIG(64) + MAC(8) + CERTID(1) + Overhead(7)¶
0b // Certificate 03 // CertificateList 01 // CertData.length 62 // CertData = 'b' 0f // CertificateVerify 4064 // Signature.length 3045...f60e // Signature 14 // Finished 35e9c34eec2c5dc1 // VerifyData¶
We would like to thank Karthikeyan Bhargavan, Owen Friel, Sean Turner, Benjamin Schwartz, Martin Thomson, and Chris Wood.¶