<?xml version="1.0" encoding="US-ASCII"?>
<?rfc toc="yes"?>
<?rfc tocompact="no"?>
<?rfc tocdepth="3"?>
<?rfc symrefs="yes"?>
<?rfc sortrefs="yes"?>
<rfc category="info" submissionType="IETF" docName="draft-smyslov-tls-ext-ext-00" ipr="trust200902">
  <front>
    <title abbrev="Extended Extensions in TLS 1.3">Extending Limit on Extensions Size in TLS 1.3</title>

    <author fullname="Valery Smyslov" initials="V." surname="Smyslov">
      <organization>ELVIS-PLUS</organization>

      <address>
        <postal>
          <street></street>
          <city></city>
          <code></code>
          <region></region>
          <country>Russian Federation</country>
        </postal>
        <phone></phone>
        <email>svan@elvis.ru</email>
      </address>
    </author>

    <date />

    <area>Security Area</area>

    <abstract>
      <t> Protocol TLS 1.3 is widely used to protect traffic in the Internet. 
      However, the format of the TLS 1.3 ClientHello, ServerHello,  and EncryptedExtensions handshake messages 
      limits the size of extensions to 64 Kbytes. 
      </t>

      <t> This specification extends TLS 1.3 to allow extensions in ClientHello, ServerHello, and EncryptedExtensions 
      have size larget than 64 Kbytes.
      </t>
    </abstract>
  </front>

  <middle>
    <section title="Introduction">
<!--      <t> Recent progress in quantum computing raised some concerns that 
      a Cryptographically Relevant Quantum Computer (CRQC) can be buils within foreseen future.
      Appearance of CRQC will make all public key cryptography systems broken.
      These systems include most modern security protocols, including TLS.
      To deal with this threat new mechanisms for calculating shared keys
      that are immune to CRQC are developed. These mechanisms are collectively
      called post-quantum Key Encapsulation Mechanisms (KEMs) and are aimed
      to replace Diffie-Hellmann key exchange in protocols.
      However, most of such mechnism have much larger public key size,
      than traditiol Diffie-Hellmann public key (based both on finite fields 
      and on elliptic curves). 
      </t>

      <t> While most post-quantum (PQ)
      Key Encapsulation Mechanisms (KEMs) have public keys beyond the maximum
      key share size limit in TLS 1.3, some KEMs have larger public keys.
      In addition, public key size for various PQ KEMs varies from
      several hundred bytes (for ML-KEM <xref target="FIPS203" />) to 
      several hundred Kbytes (for ClassicMceliece <xref target="I-D.josefsson-mceliece" />).
      </t>
-->

      <t> TLS 1.3 <xref target="RFC8446" /> was standardized in 2018 and since then 
      has become a widely used security protocol for protecting Internet traffic.
      </t>

<!--      <t> TLS 1.3 was designed before concerns about possibility of CRQC became widespread.
      It has an internal limitation for public key size to be less than 64 Kbytes,
      which makes impossible to directly use some of the most concervative PQ KEMs,
      Classic MCEliece <xref target="I-D.josefsson-mceliece" /> in it.
      This problem could be addressed by using TLS 1.2, but the IETF explicitly 
      prohibited using any PQ algorithms in TLS 1.2 <xref target="I-D.ietf-tls-tls12-frozen" />.
      There is a proposal to address this problem in a narrow way, focusing
      only on PQ KEMs <xref target="I-D.wagner-tls-keysharepqc" />.
      </t>
-->

      <t> During TLS 1.3 handshake the client first sends the ClientHello message and the server
      responds with the ServerHello message followed by the EncryptedExtensions message (<xref target="RFC8446" />, Section 2). 
      These messages contain various data needed to establish security connection, e.g., key shares for ephemeral key exchange.
      The ClientHello and ServerHello messages have few mandatory fields followed by the 
      optional extensions (<xref target="RFC8446" />, Sections 4.1.2 and 4.1.3) and the EncryptedExtensions 
      message contains only optional extensions (<xref target="RFC8446" />, Sections 4.3.1). Which extensions are included 
      is situation-dependant, so whether a particular extension is sent or not depends on the protocol variant.
      </t>

      <t> While the size of TLS 1.3 handshake messages can be up to 2^24 -1 bytes, the total size
      of extensions is limited to 2^16 - 1 bytes. This makes it impossible to use TLS 1.3 if
      the data needed to be transferred in an extension exceeds this limitation.
      One of possible example of such situation is using postquantum KEMS with large public
      keys or ciphertexts (like Classic MCEliece <xref target="I-D.josefsson-mceliece" />).
      </t>

      <t> This specification extends TLS 1.3 in to allow transferring extension data 
      larget than 64 Kbytes.
      </t>

      <t> Due to increased message size and additional round trip, this extension, when used,
      will lead to longer TLS handshake that might not be appropriate for some use cases,
      like interactive web surfing. For this reason, it is mostly aimed for long-lived 
      TLS connections, when the longer handshake is amortized by the longevity of the connection.
      </t>
    </section>

    <section title="Requirements Notation">
      <t>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 <xref target="RFC2119"></xref> <xref target="RFC8174"></xref> when,
      and only when, they appear in all capitals, as shown here.</t>

      <t> It is assumed that readers are familiar with TLS 1.3 <xref target="RFC8446" />.
      </t>
    </section>

    <section anchor="protocol" title="Protocol Overview">
        <t> This document introduces a variable-size length encoding of extensions blocks and
        individual extensions, as well as the content of each extension that contains data
        limited to 2^16 bytes. The idea is inspired by QUIC <xref target="RFC9000" /> and MLS <xref target="RFC9420" />.
        </t>

        <t> Unlike encodings in QUIC and MLS, this document allocates only one most significant
        bit to indicate what is the size of the length field, so that the length field occupies either 2 or 3 bytes.
        There is no need to have TLS extensions larger than 2^24, since this is the hard limit on the size of the TLS messages.
        The encoding is summarized in <xref target="encoding" />.
        </t>

        <table title="Length Encoding" anchor="encoding">
          <thead>
            <tr>
                <th>MSB</th>
                <th>Length</th>
                <th>Usable Bits</th>
                <th>Range</th>
            </tr>
          </thead>
          <tbody>
            <tr>
                <td>0</td>
                <td>2</td>
                <td>15</td>
                <td>0-32767</td>
            </tr>
            <tr>
                <td>1</td>
                <td>3</td>
                <td>23</td>
                <td>0-8388607</td>
            </tr>
          </tbody>
        </table>

        <t> As in QUIC, there is no requirement that length is encoded on the minimum number of bytes.
        </t>

        <t> When this specification is in use by TLS 1.3 endpoints, the encoding of extensions blocks and
        individual extensions, as well as the content of any extension inside the handshake messages that 
        contain the "extensions" field is modified as shown in <xref target="ext_ext" />,
        where the variable-size length encoding is defined as &lt;V&gt;.
        </t>

        <section title="Use of Extended Extensions" anchor="use" >

            <t> If there is a need for a client to send TLS extension that do not fit into the existing TLS 1.3 handshake messages extensions block in ClienHello
            (e.g. in case PQ KEM with large public keys, like Classic NcEliece) then the client
            indicates this with new extension of type extended_extensions (<xref target="extended_extensions" />) in the ClientHello message.
            This extension contains no data. 
            </t>

            <figure anchor="extended_extensions" align="center">
            <artwork align="left"><![CDATA[
        enum {
                ...
                extended_extensions(TBD),
                (65535)
            } ExtensionType;
            ]]></artwork>
            </figure>

            <t> If the server supports this extension, it replies with the HelloRetryRequest that also includes 
            the extended_extensions extension.
            </t>

            <t> Once HelloRetryRequest has been received, the client repeats ClienHello re-formatting it in such a way,
            that the extensions block with the variable-size length encoding as per <xref target="ext_ext" />. Note that unless the extension exceeds
            32767 bytes in size, no changes of the bits on the wire occured with new encoding.
            </t>

            <t> The server then responds with ServerHello that also includes the extensions block encoded
            in accordance with <xref target="ext_ext" />.
            </t>

            <figure anchor="handshake" title="Message Flow" align="center">
            <artwork align="left"><![CDATA[
            Client                                               Server

            ClientHello
            + key_share
            + extended_extensions  -------->
                                                      HelloRetryRequest
                                                            + key_share
                                   <--------      + extended_extensions
            <ClientHello>
            + key_share
            + extended_extensions  -------->
                                                          <ServerHello>
                                                            + key_share
                                                  + extended_extensions
                                                      AuxHandshakeData*
                                                {<EncryptedExtensions>}
                                                  {CertificateRequest*}
                                                       {<Certificate>*}
                                                   {CertificateVerify*}
                                                             {Finished}
                                    <--------       [Application Data*]
            {<Certificate>*}
            {CertificateVerify*}
            {Finished}              -------->
            [Application Data]      <------->        [Application Data]


            <> Indicates messages that contain extension
               blocks encoded with variable-size length encoding.

            ]]></artwork>
            </figure>

            <t> Note that once the extended extensions are negotiated, all susequent TLS handshake messages for this TLS session that 
            include the extensions blocks <bcp14>MUST</bcp14> use the variable-size length encodings for them.
            </t>
        </section>
    </section>

    <section anchor="iana" title="IANA Considerations">
        <t> IANA is requested to assign a new value from the TLS ExtensionType Values registry:

            <figure align="center">
            <artwork align="left"><![CDATA[
        *  The Extension Name should be extended_extensions

        *  The TLS 1.3 value should be CH,SH,HRR

        *  The DTLS-Only value should be N

        *  The Recommended value should be Y
            ]]></artwork>
            </figure>

        </t>
    </section>

    <section anchor="security" title="Security Considerations">
        <t> The extended extensions mechanism defined in this document only affects the encoding
        of TLS 1.3 messages. It does not change security properties of TLS 1.3 defined in <xref target="RFC8446" />.
        </t>
    </section>

  </middle>

    <back>
    <references title="Normative References">
        <?rfc include="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.2119.xml"?>
        <?rfc include="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8174.xml"?>
        <?rfc include="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8446.xml"?>
    </references>

    <references title="Informative References">
        <?rfc include="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.9000.xml"?>
        <?rfc include="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.9420.xml"?>
        <?rfc include="https://xml2rfc.ietf.org/public/rfc/bibxml3/reference.I-D.josefsson-mceliece.xml" ?>
    </references>

    <section title="Extended Extensions" anchor="ext_ext" >
        <t> This appendix contains an excerpt from Appendix B.3 of <xref target="RFC8446" />,
        with the changes in encoding that this specification defines. The numeration of subsections from 
        <xref target="RFC8446" /> is preserved and for convenience numbers are quoted.
        </t>

        <figure align="center">
        <artwork align="left"><![CDATA[

"B.3.1."  Key Exchange Messages

    uint16 ProtocolVersion;
    opaque Random[32];

    uint8 CipherSuite[2];    /* Cryptographic suite selector */

    struct {
        ProtocolVersion legacy_version = 0x0303;    /* TLS v1.2 */
        Random random;
        opaque legacy_session_id<0..32>;
        CipherSuite cipher_suites<2..2^16-2>;
        opaque legacy_compression_methods<1..2^8-1>;
        Extension extensions<V>;                    /* 8..2^23-1 */
    } ClientHello;

    struct {
        ProtocolVersion legacy_version = 0x0303;    /* TLS v1.2 */
        Random random;
        opaque legacy_session_id_echo<0..32>;
        CipherSuite cipher_suite;
        uint8 legacy_compression_method = 0;
        Extension extensions<V>;                    /* 6..2^23-1 */
    } ServerHello;

    struct {
        ExtensionType extension_type;
        opaque extension_data<V>;                   /* 0..2^23-1 */
    } Extension;

    enum {
        server_name(0),                             /* RFC 6066 */
        max_fragment_length(1),                     /* RFC 6066 */
        status_request(5),                          /* RFC 6066 */
        supported_groups(10),                       /* RFC 8422, 7919 */
        signature_algorithms(13),                   /* RFC 8446 */
        use_srtp(14),                               /* RFC 5764 */
        heartbeat(15),                              /* RFC 6520 */
        application_layer_protocol_negotiation(16), /* RFC 7301 */
        signed_certificate_timestamp(18),           /* RFC 6962 */
        client_certificate_type(19),                /* RFC 7250 */
        server_certificate_type(20),                /* RFC 7250 */
        padding(21),                                /* RFC 7685 */
        RESERVED(40),                               /* Used but never
                                                       assigned */
        pre_shared_key(41),                         /* RFC 8446 */
        early_data(42),                             /* RFC 8446 */
        supported_versions(43),                     /* RFC 8446 */
        cookie(44),                                 /* RFC 8446 */
        psk_key_exchange_modes(45),                 /* RFC 8446 */
        RESERVED(46),                               /* Used but never
                                                       assigned */
        certificate_authorities(47),                /* RFC 8446 */
        oid_filters(48),                            /* RFC 8446 */
        post_handshake_auth(49),                    /* RFC 8446 */
        signature_algorithms_cert(50),              /* RFC 8446 */
        key_share(51),                              /* RFC 8446 */
        (65535)
    } ExtensionType;

    struct {
        NamedGroup group;
        opaque key_exchange<V>;                     /* 1..2^23-1 */
    } KeyShareEntry;

    struct {
        KeyShareEntry client_shares<V>;             /* 0..2^23-1 */
    } KeyShareClientHello;

    struct {
        NamedGroup selected_group;
    } KeyShareHelloRetryRequest;

    struct {
        KeyShareEntry server_share;
    } KeyShareServerHello;

    struct {
        uint8 legacy_form = 4;
        opaque X[coordinate_length];
        opaque Y[coordinate_length];
    } UncompressedPointRepresentation;

    enum { psk_ke(0), psk_dhe_ke(1), (255) } PskKeyExchangeMode;

    struct {
        PskKeyExchangeMode ke_modes<1..255>;
    } PskKeyExchangeModes;

    struct {} Empty;

    struct {
        select (Handshake.msg_type) {
            case new_session_ticket:   uint32 max_early_data_size;
            case client_hello:         Empty;
            case encrypted_extensions: Empty;
        };
    } EarlyDataIndication;

    struct {
        opaque identity<V>;                         /* 1..2^23-1 */
        uint32 obfuscated_ticket_age;
    } PskIdentity;

    opaque PskBinderEntry<32..255>;

    struct {
        PskIdentity identities<V>;                  /* 7..2^23-1 */
        PskBinderEntry binders<V>;                  /* 33..2^23-1 */
    } OfferedPsks;

    struct {
        select (Handshake.msg_type) {
            case client_hello: OfferedPsks;
            case server_hello: uint16 selected_identity;
        };
    } PreSharedKeyExtension;

"B.3.1.1."  Version Extension

      struct {
          select (Handshake.msg_type) {
              case client_hello:
                   ProtocolVersion versions<2..254>;

              case server_hello: /* and HelloRetryRequest */
                   ProtocolVersion selected_version;
          };
      } SupportedVersions;

"B.3.1.2."  Cookie Extension

      struct {
          opaque cookie<V>;                         /* 1..2^23-1 */
      } Cookie;

"B.3.1.3."  Signature Algorithm Extension

      enum {
          /* RSASSA-PKCS1-v1_5 algorithms */
          rsa_pkcs1_sha256(0x0401),
          rsa_pkcs1_sha384(0x0501),
          rsa_pkcs1_sha512(0x0601),

          /* ECDSA algorithms */
          ecdsa_secp256r1_sha256(0x0403),
          ecdsa_secp384r1_sha384(0x0503),
          ecdsa_secp521r1_sha512(0x0603),

          /* RSASSA-PSS algorithms with public key OID rsaEncryption */
          rsa_pss_rsae_sha256(0x0804),
          rsa_pss_rsae_sha384(0x0805),
          rsa_pss_rsae_sha512(0x0806),

          /* EdDSA algorithms */
          ed25519(0x0807),
          ed448(0x0808),

          /* RSASSA-PSS algorithms with public key OID RSASSA-PSS */
          rsa_pss_pss_sha256(0x0809),
          rsa_pss_pss_sha384(0x080a),
          rsa_pss_pss_sha512(0x080b),

          /* Legacy algorithms */
          rsa_pkcs1_sha1(0x0201),
          ecdsa_sha1(0x0203),

          /* Reserved Code Points */
          obsolete_RESERVED(0x0000..0x0200),
          dsa_sha1_RESERVED(0x0202),
          obsolete_RESERVED(0x0204..0x0400),
          dsa_sha256_RESERVED(0x0402),
          obsolete_RESERVED(0x0404..0x0500),
          dsa_sha384_RESERVED(0x0502),
          obsolete_RESERVED(0x0504..0x0600),
          dsa_sha512_RESERVED(0x0602),
          obsolete_RESERVED(0x0604..0x06FF),
          private_use(0xFE00..0xFFFF),
          (0xFFFF)
      } SignatureScheme;

      struct {
          SignatureScheme supported_signature_algorithms<V>; 
                                                    /* 2..2^23-2 */
      } SignatureSchemeList;

"B.3.1.4."  Supported Groups Extension

      enum {
          unallocated_RESERVED(0x0000),

          /* Elliptic Curve Groups (ECDHE) */
          obsolete_RESERVED(0x0001..0x0016),
          secp256r1(0x0017), secp384r1(0x0018), secp521r1(0x0019),
          obsolete_RESERVED(0x001A..0x001C),
          x25519(0x001D), x448(0x001E),

          /* Finite Field Groups (DHE) */
          ffdhe2048(0x0100), ffdhe3072(0x0101), ffdhe4096(0x0102),
          ffdhe6144(0x0103), ffdhe8192(0x0104),

          /* Reserved Code Points */
          ffdhe_private_use(0x01FC..0x01FF),
          ecdhe_private_use(0xFE00..0xFEFF),
          obsolete_RESERVED(0xFF01..0xFF02),
          (0xFFFF)
      } NamedGroup;

      struct {
          NamedGroup named_group_list<V>;           /* 2..2^23-1 */
      } NamedGroupList;

"B.3.2."  Server Parameters Messages

      opaque DistinguishedName<V>;                  /* 1..2^23-1 */

      struct {
          DistinguishedName authorities<V>;         /* 3..2^23-1 */
      } CertificateAuthoritiesExtension;

      struct {
          opaque certificate_extension_oid<1..2^8-1>;
          opaque certificate_extension_values<V>;   /* 0..2^23-1 */
      } OIDFilter;

      struct {
          OIDFilter filters<V>;                     /* 0..2^23-1 */
      } OIDFilterExtension;

      struct {} PostHandshakeAuth;

      struct {
          Extension extensions<V>;                  /* 0..2^23-1 */
      } EncryptedExtensions;

      struct {
          opaque certificate_request_context<0..2^8-1>;
          Extension extensions<V>;                  /* 2..2^23-1 */
      } CertificateRequest;

"B.3.3."  Authentication Messages

      enum {
          X509(0),
          OpenPGP_RESERVED(1),
          RawPublicKey(2),
          (255)
      } CertificateType;

      struct {
          select (certificate_type) {
              case RawPublicKey:
                /* From RFC 7250 ASN.1_subjectPublicKeyInfo */
                opaque ASN1_subjectPublicKeyInfo<1..2^24-1>;

              case X509:
                opaque cert_data<1..2^24-1>;
          };
          Extension extensions<V>;                  /* 0..2^23-1 */
      } CertificateEntry;

      struct {
          opaque certificate_request_context<0..2^8-1>;
          CertificateEntry certificate_list<0..2^24-1>;
      } Certificate;

      struct {
          SignatureScheme algorithm;
          opaque signature<0..2^16-1>;
      } CertificateVerify;

      struct {
          opaque verify_data[Hash.length];
      } Finished;

"B.3.4."  Ticket Establishment

      struct {
          uint32 ticket_lifetime;
          uint32 ticket_age_add;
          opaque ticket_nonce<0..255>;
          opaque ticket<1..2^16-1>;
          Extension extensions<V>;                  /* 0..2^23-2 */
      } NewSessionTicket;

"B.3.5."  Updating Keys

      struct {} EndOfEarlyData;

      enum {
          update_not_requested(0), update_requested(1), (255)
      } KeyUpdateRequest;

      struct {
          KeyUpdateRequest request_update;
      } KeyUpdate;

      ]]></artwork>
      </figure>

    </section>

    <section anchor="ack" title="Acknowledgements" numbered="false">
        <t> Eric Rescorla proposed the idea to use QUIC- and MLS-like variable-size length encoding in TLS 1.3.
        </t>
    </section>

  </back>
</rfc>

