| rfc9849v1.md | rfc9849.md | |||
|---|---|---|---|---|
| skipping to change at line 24 ¶ | skipping to change at line 24 ¶ | |||
| area: SEC | area: SEC | |||
| workgroup: tls | workgroup: tls | |||
| keyword: | keyword: | |||
| stand_alone: yes | stand_alone: yes | |||
| pi: [toc, sortrefs, symrefs] | pi: [toc, sortrefs, symrefs] | |||
| author: | author: | |||
| - name: Eric Rescorla | - name: Eric Rescorla | |||
| ins: E. Rescorla | ins: E. Rescorla | |||
| org: Independent | org: Knight-Georgetown Institute | |||
| email: ekr@rtfm.com | email: ekr@rtfm.com | |||
| - name: Kazuho Oku | - name: Kazuho Oku | |||
| ins: K. Oku | ins: K. Oku | |||
| org: Fastly | org: Fastly | |||
| email: kazuhooku@gmail.com | email: kazuhooku@gmail.com | |||
| - name: Nick Sullivan | - name: Nick Sullivan | |||
| ins: N. Sullivan | ins: N. Sullivan | |||
| org: Cryptography Consulting LLC | org: Cryptography Consulting LLC | |||
| email: nicholas.sullivan+ietf@gmail.com | email: nicholas.sullivan+ietf@gmail.com | |||
| - name: Christopher A. Wood | - name: Christopher A. Wood | |||
| ins: C. A. Wood | ins: C. A. Wood | |||
| org: Cloudflare | org: Cloudflare | |||
| email: caw@heapingbits.net | email: caw@heapingbits.net | |||
| normative: | normative: | |||
| RFC2119: | RFC2119: | |||
| RFC7918: | RFC7918: | |||
| RFC9180: | ||||
| display: HPKE | ||||
| informative: | ||||
| RFCYYY1: | RFCYYY1: | |||
| title: > | title: > | |||
| Bootstrapping TLS Encrypted ClientHello with DNS Service Bindings | Bootstrapping TLS Encrypted ClientHello with DNS Service Bindings | |||
| target: https://www.rfc-editor.org/info/rfcYYY1 | target: https://www.rfc-editor.org/info/rfcYYY1 | |||
| seriesinfo: | seriesinfo: | |||
| RFC: YYY1 | RFC: YYY1 | |||
| DOI: 10.17487/RFCYYY1 | DOI: 10.17487/RFCYYY1 | |||
| date: November 2025 | date: November 2025 | |||
| author: | author: | |||
| - | - | |||
| skipping to change at line 67 ¶ | skipping to change at line 72 ¶ | |||
| fullname: Benjamin M. Schwartz | fullname: Benjamin M. Schwartz | |||
| - | - | |||
| ins: M. Bishop | ins: M. Bishop | |||
| surname: Bishop | surname: Bishop | |||
| fullname: Mike Bishop | fullname: Mike Bishop | |||
| - | - | |||
| ins: E. Nygren | ins: E. Nygren | |||
| surname: Nygren | surname: Nygren | |||
| fullname: Erik Nygren | fullname: Erik Nygren | |||
| RFC9180: | ||||
| display: HPKE | ||||
| informative: | ||||
| WHATWG-IPV4: | WHATWG-IPV4: | |||
| author: | author: | |||
| - | - | |||
| org: WHATWG | org: WHATWG | |||
| title: "URL - IPv4 Parser" | title: "URL - IPv4 Parser" | |||
| target: https://url.spec.whatwg.org/#concept-ipv4-parser | target: https://url.spec.whatwg.org/#concept-ipv4-parser | |||
| date: May 2021 | date: May 2021 | |||
| refcontent: | refcontent: | |||
| "WHATWG Living Standard" | "WHATWG Living Standard" | |||
| skipping to change at line 128 ¶ | skipping to change at line 129 ¶ | |||
| We recommend updating this reference to the most current version of the WHATWG | We recommend updating this reference to the most current version of the WHATWG | |||
| Living Standard, replacing the URL with the more general URL to the standard | Living Standard, replacing the URL with the more general URL to the standard | |||
| (https://url.spec.whatwg.org/), and adding a "commit snapshot" URL to the | (https://url.spec.whatwg.org/), and adding a "commit snapshot" URL to the | |||
| reference. | reference. | |||
| Current: | Current: | |||
| [WHATWG-IPV4] | [WHATWG-IPV4] | |||
| WHATWG, "URL - IPv4 Parser", WHATWG Living Standard, May | WHATWG, "URL - IPv4 Parser", WHATWG Living Standard, May | |||
| 2021, <https://url.spec.whatwg.org/#concept-ipv4-parser>. | 2021, <https://url.spec.whatwg.org/#concept-ipv4-parser>. | |||
| b) RFC 6125 has been obsoleted by RFC 9525. May we replace RFC 6125 | EKR: Per MT, WHATWG has asked us not to do that. We should leave | |||
| with RFC 9525? | this as-is and change the date to December 2025. | |||
| c) Informative Reference RFC 5077 has been obsoleted by RFC 8446. We | rfced: For context, we reached out to WHATWG in September about a format for | |||
| recommend replacing RFC 5077 with RFC 8446. However, if RFC 5077 must be | references to their standards (see: | |||
| referenced, we suggest mentioning RFC 8446 (e.g., RFC 5077 has been obsoleted | https://github.com/whatwg/meta/issues/363). The proposed update below for this | |||
| by RFC 8446). See Section 4.8.6 in the RFC Style Guide (RFC 7322). | reference reflects the approved format. It would be helpful for the RPC to | |||
| know what WHATWG has asked authors to not do so that we can reach out for | ||||
| clarification and update our recommended citation accordingly. | ||||
| Perhaps: | ||||
| [WHATWG-IPV4] | ||||
| WHATWG, "URL - IPv4 Parser", WHATWG Living Standard, | ||||
| <https://url.spec.whatwg.org/#concept-ipv4-parser>. | ||||
| Commit snapshot: | ||||
| https://url.spec.whatwg.org/commit-snapshots/1b8b8c55eb4bed9f139c9a439fb1c | ||||
| 1bf5566b619/#concept-ipv4-parser | ||||
| Regarding the date, we don't recommend using a future date for a reference as | ||||
| it doesn't reflect the date for a currently published work (unless there is an | ||||
| anticipated update to the WHATWG specification in December 2025). | ||||
| d) FYI, RFCYYY1 (draft-ietf-tls-svcb-ech) will be updated during the XML stage. | d) FYI, RFCYYY1 (draft-ietf-tls-svcb-ech) will be updated during the XML stage. | |||
| <!-- [rfced] Please insert any keywords (beyond those that appear in | OK. | |||
| the title) for use on https://www.rfc-editor.org/search. --> | --> | |||
| -> | ||||
| This document describes a mechanism in Transport Layer Security (TLS) for | This document describes a mechanism in Transport Layer Security (TLS) for | |||
| encrypting a ClientHello message under a server public key. | encrypting a ClientHello message under a server public key. | |||
| --- middle | --- middle | |||
| # Introduction {#intro} | # Introduction {#intro} | |||
| Although TLS 1.3 {{!RFC8446}} encrypts most of the handshake, including the | Although TLS 1.3 {{!RFC8446}} encrypts most of the handshake, including the | |||
| server certificate, there are several ways in which an on-path attacker can | server certificate, there are several ways in which an on-path attacker can | |||
| learn private information about the connection. The plaintext Server Name | learn private information about the connection. The plaintext Server Name | |||
| Indication (SNI) extension in ClientHello messages, which leaks the target | Indication (SNI) extension in ClientHello messages, which leaks the target | |||
| domain for a given connection, is perhaps the most sensitive information | domain for a given connection, is perhaps the most sensitive information | |||
| left unencrypted in TLS 1.3. | left unencrypted in TLS 1.3. | |||
| This document specifies a new TLS extension called Encrypted Client Hello | This document specifies a new TLS extension called Encrypted Client | |||
| (ECH) that allows clients to encrypt their ClientHello to the TLS server. | Hello (ECH) that allows clients to encrypt their ClientHello to the | |||
| This protects the SNI and other potentially sensitive fields, such as the | TLS server. This protects the SNI and other potentially sensitive | |||
| Application-Layer Protocol Negotiation (ALPN) list {{?RFC7301}}. Co-located servers w | fields, such as the Application-Layer Protocol Negotiation (ALPN) list | |||
| ith consistent externally visible TLS | {{?RFC7301}}. Co-located servers with consistent externally visible | |||
| configurations and behavior, including supported versions and cipher suites and | TLS configurations and behavior, including supported versions and cipher suites and | |||
| how they respond to incoming client connections, form an anonymity set. (Note | how they respond to incoming client connections, form an anonymity set. (Note | |||
| that implementation-specific choices, such as extension ordering within TLS | that implementation-specific choices, such as extension ordering within TLS | |||
| messages or division of data into record-layer boundaries, can result in | messages or division of data into record-layer boundaries, can result in | |||
| different externally visible behavior, even for servers with consistent TLS | different externally visible behavior, even for servers with consistent TLS | |||
| configurations.) Usage of this mechanism reveals that a client is connecting | configurations.) Usage of this mechanism reveals that a client is connecting | |||
| to a particular service provider, but does not reveal which server from the | to a particular service provider, but does not reveal which server from the | |||
| anonymity set terminates the connection. Deployment implications of this | anonymity set terminates the connection. Deployment implications of this | |||
| feature are discussed in {{deployment}}. | feature are discussed in {{deployment}}. | |||
| ECH is not in itself sufficient to protect the identity of the server. | ECH is not in itself sufficient to protect the identity of the server. | |||
| skipping to change at line 233 ¶ | skipping to change at line 248 ¶ | |||
| | | | | | | | | | | |||
| | 2001:DB8::1111 | | 2001:DB8::EEEE | | | 2001:DB8::1111 | | 2001:DB8::EEEE | | |||
| Client <----------------------------->| | | Client <----------------------------->| | | |||
| | public.example.com | | private.example.org | | | public.example.com | | private.example.org | | |||
| | | | | | | | | | | |||
| +--------------------+ +---------------------+ | +--------------------+ +---------------------+ | |||
| Client-Facing Server Backend Server | Client-Facing Server Backend Server | |||
| ~~~~ | ~~~~ | |||
| {: #split-mode title="Split Mode Topology"} | {: #split-mode title="Split Mode Topology"} | |||
| In Split Mode, the provider is not the origin server for private domains. | In split mode, the provider is not the origin server for private domains. | |||
| Rather, the DNS records for private domains point to the provider, and the | Rather, the DNS records for private domains point to the provider, and the | |||
| provider's server relays the connection back to the origin server, who | provider's server relays the connection back to the origin server, who | |||
| terminates the TLS connection with the client. Importantly, the service provider | terminates the TLS connection with the client. Importantly, the service provider | |||
| does not have access to the plaintext of the connection beyond the unencrypted | does not have access to the plaintext of the connection beyond the unencrypted | |||
| portions of the handshake. | portions of the handshake. | |||
| In the remainder of this document, we will refer to the ECH-service provider as | In the remainder of this document, we will refer to the ECH-service provider as | |||
| the "client-facing server" and the TLS terminator as the "backend server". | the "client-facing server" and to the TLS terminator as the "backend server". | |||
| These are the same entity in Shared Mode, but in Split Mode, the client-facing | These are the same entity in Shared Mode, but in split mode, the client-facing | |||
| and backend servers are physically separated. | and backend servers are physically separated. | |||
| See {{security-considerations}} for more discussion about the ECH threat model | See {{security-considerations}} for more discussion about the ECH threat model | |||
| and how it relates to the client, client-facing server, and backend server. | and how it relates to the client, client-facing server, and backend server. | |||
| ## Encrypted ClientHello (ECH) | ## Encrypted ClientHello (ECH) | |||
| A client-facing server enables ECH by publishing an ECH configuration, which | A client-facing server enables ECH by publishing an ECH configuration, which | |||
| is an encryption public key and associated metadata. Domains which wish to | is an encryption public key and associated metadata. Domains which wish to | |||
| use ECH must publish this configuration, using the key associated | use ECH must publish this configuration, using the key associated | |||
| skipping to change at line 711 ¶ | skipping to change at line 726 ¶ | |||
| ClientHelloOuter.random using a secure random number generator. (See | ClientHelloOuter.random using a secure random number generator. (See | |||
| {{flow-client-reaction}}.) | {{flow-client-reaction}}.) | |||
| 1. It SHOULD place the value of `ECHConfig.contents.public_name` in the | 1. It SHOULD place the value of `ECHConfig.contents.public_name` in the | |||
| "server_name" extension. Clients that do not follow this step, or place a | "server_name" extension. Clients that do not follow this step, or place a | |||
| different value in the "server_name" extension, risk breaking the retry | different value in the "server_name" extension, risk breaking the retry | |||
| mechanism described in {{rejected-ech}} or failing to interoperate with | mechanism described in {{rejected-ech}} or failing to interoperate with | |||
| servers that require this step to be done; see {{client-facing-server}}. | servers that require this step to be done; see {{client-facing-server}}. | |||
| 1. When the client offers the "pre_shared_key" extension in ClientHelloInner, it | 1. When the client offers the "pre_shared_key" extension in ClientHelloInner, it | |||
| SHOULD also include a GREASE "pre_shared_key" extension in ClientHelloOuter, | SHOULD also include a GREASE "pre_shared_key" extension in ClientHelloOuter, | |||
| generated in the manner described in {{grease-psk}}. The client MUST NOT use | generated in the manner described in {{grease-psk}}. The client MUST NOT use | |||
| this extension to advertise a Pre-Shared Key (PSK) to the client-facing server. (S ee | this extension to advertise a PSK to the client-facing server. (See | |||
| {{flow-clienthello-malleability}}.) When the client includes a GREASE | {{flow-clienthello-malleability}}.) When the client includes a GREASE | |||
| "pre_shared_key" extension, it MUST also copy the "psk_key_exchange_modes" | "pre_shared_key" extension, it MUST also copy the "psk_key_exchange_modes" | |||
| from the ClientHelloInner into the ClientHelloOuter. | from the ClientHelloInner into the ClientHelloOuter. | |||
| 1. When the client offers the "early_data" extension in ClientHelloInner, it | 1. When the client offers the "early_data" extension in ClientHelloInner, it | |||
| MUST also include the "early_data" extension in ClientHelloOuter. This | MUST also include the "early_data" extension in ClientHelloOuter. This | |||
| allows servers that reject ECH and use ClientHelloOuter to safely ignore any | allows servers that reject ECH and use ClientHelloOuter to safely ignore any | |||
| early data sent by the client per {{RFC8446, Section 4.2.10}}. | early data sent by the client per {{RFC8446, Section 4.2.10}}. | |||
| The client might duplicate non-sensitive extensions in both messages. However, | The client might duplicate non-sensitive extensions in both messages. However, | |||
| implementations need to take care to ensure that sensitive extensions are not | implementations need to take care to ensure that sensitive extensions are not | |||
| skipping to change at line 870 ¶ | skipping to change at line 885 ¶ | |||
| ECH. Otherwise, if it has a length other than 8, the client aborts the handshake | ECH. Otherwise, if it has a length other than 8, the client aborts the handshake | |||
| with a "decode_error" alert. Otherwise, the client computes | with a "decode_error" alert. Otherwise, the client computes | |||
| `hrr_accept_confirmation` as described in {{backend-server-hrr}}. If this value | `hrr_accept_confirmation` as described in {{backend-server-hrr}}. If this value | |||
| matches the extension payload, the server has accepted ECH. Otherwise, it has | matches the extension payload, the server has accepted ECH. Otherwise, it has | |||
| rejected ECH. | rejected ECH. | |||
| If the server accepts ECH, the client handshakes with ClientHelloInner as | If the server accepts ECH, the client handshakes with ClientHelloInner as | |||
| described in {{accepted-ech}}. Otherwise, the client handshakes with | described in {{accepted-ech}}. Otherwise, the client handshakes with | |||
| ClientHelloOuter as described in {{rejected-ech}}. | ClientHelloOuter as described in {{rejected-ech}}. | |||
| <!-- [rfced] In the following sentence, does "length other than 8" refer to | ||||
| bytes? If yes, may we update as follows? | ||||
| Current: | ||||
| Otherwise, if it has a length other than 8, the client aborts the | ||||
| handshake with a "decode_error" alert. | ||||
| Perhaps: | ||||
| Otherwise, if it has a length other than 8 bytes, the client aborts | ||||
| the handshake with a "decode_error" alert. --> | ||||
| ### Handshaking with ClientHelloInner {#accepted-ech} | ### Handshaking with ClientHelloInner {#accepted-ech} | |||
| If the server accepts ECH, the client proceeds with the connection as in | If the server accepts ECH, the client proceeds with the connection as in | |||
| {{RFC8446}}, with the following modifications: | {{RFC8446}}, with the following modifications: | |||
| The client behaves as if it had sent ClientHelloInner as the ClientHello. That | The client behaves as if it had sent ClientHelloInner as the ClientHello. That | |||
| is, it evaluates the handshake using the ClientHelloInner's preferences, and, | is, it evaluates the handshake using the ClientHelloInner's preferences, and, | |||
| when computing the transcript hash ({{Section 4.4.1 of RFC8446}}), it uses | when computing the transcript hash ({{Section 4.4.1 of RFC8446}}), it uses | |||
| ClientHelloInner as the first ClientHello. | ClientHelloInner as the first ClientHello. | |||
| skipping to change at line 981 ¶ | skipping to change at line 985 ¶ | |||
| a node with configuration B in the second. Note that this guidance | a node with configuration B in the second. Note that this guidance | |||
| does not apply to the cases in the previous paragraph where the server | does not apply to the cases in the previous paragraph where the server | |||
| has securely disabled ECH. | has securely disabled ECH. | |||
| If a client does not retry, it MUST report an error to the calling | If a client does not retry, it MUST report an error to the calling | |||
| application. | application. | |||
| ### Authenticating for the Public Name {#auth-public-name} | ### Authenticating for the Public Name {#auth-public-name} | |||
| When the server rejects ECH, it continues with the handshake using the plaintext | When the server rejects ECH, it continues with the handshake using the plaintext | |||
| "server_name" extension instead (see {{server-behavior}}). Then, clients that offer | "server_name" extension instead (see {{server-behavior}}). Clients that offer | |||
| ECH authenticate the connection with the public name as follows: | ECH then authenticate the connection with the public name as follows: | |||
| - The client MUST verify that the certificate is valid for | - The client MUST verify that the certificate is valid for | |||
| ECHConfig.contents.public_name. If invalid, it MUST abort the connection with | ECHConfig.contents.public_name. If invalid, it MUST abort the connection with | |||
| the appropriate alert. | the appropriate alert. | |||
| - If the server requests a client certificate, the client MUST respond with an | - If the server requests a client certificate, the client MUST respond with an | |||
| empty Certificate message, denoting no client certificate. | empty Certificate message, denoting no client certificate. | |||
| In verifying the client-facing server certificate, the client MUST | In verifying the client-facing server certificate, the client MUST | |||
| interpret the public name as a DNS-based reference identity | interpret the public name as a DNS-based reference identity | |||
| {{!RFC6125}}. Clients that incorporate DNS names and IP addresses into | {{!RFC9525}}. Clients that incorporate DNS names and IP addresses into | |||
| the same syntax (e.g. {{Section 7.4 of ?RFC3986}} and {{WHATWG-IPV4}}) | the same syntax (e.g. {{Section 7.4 of ?RFC3986}} and {{WHATWG-IPV4}}) | |||
| MUST reject names that would be interpreted as IPv4 addresses. | MUST reject names that would be interpreted as IPv4 addresses. | |||
| Clients that enforce this by checking ECHConfig.contents.public_name | Clients that enforce this by checking ECHConfig.contents.public_name | |||
| do not need to repeat the check when processing ECH rejection. | do not need to repeat the check when processing ECH rejection. | |||
| Note that authenticating a connection for the public name does not authenticate | Note that authenticating a connection for the public name does not authenticate | |||
| it for the origin. The TLS implementation MUST NOT report such connections as | it for the origin. The TLS implementation MUST NOT report such connections as | |||
| successful to the application. It additionally MUST ignore all session tickets | successful to the application. It additionally MUST ignore all session tickets | |||
| and session IDs presented by the server. These connections are only used to | and session IDs presented by the server. These connections are only used to | |||
| trigger retries, as described in {{rejected-ech}}. This may be implemented, for | trigger retries, as described in {{rejected-ech}}. This may be implemented, for | |||
| skipping to change at line 1096 ¶ | skipping to change at line 1100 ¶ | |||
| If the server sends an "encrypted_client_hello" extension in either | If the server sends an "encrypted_client_hello" extension in either | |||
| HelloRetryRequest or EncryptedExtensions, the client MUST check the extension | HelloRetryRequest or EncryptedExtensions, the client MUST check the extension | |||
| syntactically and abort the connection with a "decode_error" alert if it is | syntactically and abort the connection with a "decode_error" alert if it is | |||
| invalid. It otherwise ignores the extension. It MUST NOT save the | invalid. It otherwise ignores the extension. It MUST NOT save the | |||
| "retry_configs" value in EncryptedExtensions. | "retry_configs" value in EncryptedExtensions. | |||
| Offering a GREASE extension is not considered offering an encrypted ClientHello | Offering a GREASE extension is not considered offering an encrypted ClientHello | |||
| for purposes of requirements in {{real-ech}}. In particular, the client | for purposes of requirements in {{real-ech}}. In particular, the client | |||
| MAY offer to resume sessions established without ECH. | MAY offer to resume sessions established without ECH. | |||
| <!-- [rfced] It seems that "client" was intended to be "clients" (plural) in | ||||
| the sentence below and updated as follows. Please let us know if that is not | ||||
| accurate. | ||||
| Original: | ||||
| Correctly-implemented client will ignore those extensions. | ||||
| Current: | ||||
| Correctly implemented clients will ignore those extensions. | ||||
| ### Server Greasing | ### Server Greasing | |||
| {{config-extensions-iana}} describes a set of Reserved extensions | {{config-extensions-iana}} describes a set of Reserved extensions | |||
| which will never be registered. These can be used by servers to | which will never be registered. These can be used by servers to | |||
| "grease" the contents of the ECH configuration, as inspired by | "grease" the contents of the ECH configuration, as inspired by | |||
| {{?RFC8701}}. This helps ensure clients process ECH extensions | {{?RFC8701}}. This helps ensure clients process ECH extensions | |||
| correctly. When constructing ECH configurations, servers SHOULD | correctly. When constructing ECH configurations, servers SHOULD | |||
| randomly select from reserved values with the high-order bit | randomly select from reserved values with the high-order bit | |||
| clear. Correctly implemented clients will ignore those extensions. | clear. Correctly implemented clients will ignore those extensions. | |||
| skipping to change at line 1307 ¶ | skipping to change at line 1300 ¶ | |||
| "encrypted_client_hello" extension in its EncryptedExtensions with the | "encrypted_client_hello" extension in its EncryptedExtensions with the | |||
| "retry_configs" field set to one or more ECHConfig structures with up-to-date | "retry_configs" field set to one or more ECHConfig structures with up-to-date | |||
| keys, as described in {{client-facing-server}}. | keys, as described in {{client-facing-server}}. | |||
| Note that a client-facing server that forwards the first ClientHello cannot | Note that a client-facing server that forwards the first ClientHello cannot | |||
| include its own "cookie" extension if the backend server sends a | include its own "cookie" extension if the backend server sends a | |||
| HelloRetryRequest. This means that the client-facing server either needs to | HelloRetryRequest. This means that the client-facing server either needs to | |||
| maintain state for such a connection or it needs to coordinate with the backend | maintain state for such a connection or it needs to coordinate with the backend | |||
| server to include any information it requires to process the second ClientHello. | server to include any information it requires to process the second ClientHello. | |||
| <!-- [rfced] May we rephrase the following text for an improved sentence flow? | ||||
| Original: | ||||
| The backend server embeds in ServerHello.random a string derived from | ||||
| the inner handshake. | ||||
| Perhaps: | ||||
| A string derived from the inner handshake is embedded into | ||||
| ServerHello.random by the backend server. --> | ||||
| ## Backend Server {#backend-server} | ## Backend Server {#backend-server} | |||
| Upon receipt of an "encrypted_client_hello" extension of type `inner` in a | Upon receipt of an "encrypted_client_hello" extension of type `inner` in a | |||
| ClientHello, if the backend server negotiates TLS 1.3 or higher, then it MUST | ClientHello, if the backend server negotiates TLS 1.3 or higher, then it MUST | |||
| confirm ECH acceptance to the client by computing its ServerHello as described | confirm ECH acceptance to the client by computing its ServerHello as described | |||
| here. | here. | |||
| The backend server embeds in ServerHello.random a string derived from the inner | The backend server embeds in ServerHello.random a string derived from the inner | |||
| handshake. It begins by computing its ServerHello as usual, except the last 8 | handshake. It begins by computing its ServerHello as usual, except the last 8 | |||
| bytes of ServerHello.random are set to zero. It then computes the transcript | bytes of ServerHello.random are set to zero. It then computes the transcript | |||
| skipping to change at line 1432 ¶ | skipping to change at line 1415 ¶ | |||
| DNS results, if one is provided. | DNS results, if one is provided. | |||
| In order to ensure that the retry mechanism works successfully, servers | In order to ensure that the retry mechanism works successfully, servers | |||
| SHOULD ensure that every endpoint which might receive a TLS connection | SHOULD ensure that every endpoint which might receive a TLS connection | |||
| is provisioned with an appropriate certificate for the public name. | is provisioned with an appropriate certificate for the public name. | |||
| This is especially important during periods of server reconfiguration | This is especially important during periods of server reconfiguration | |||
| when different endpoints might have different configurations. | when different endpoints might have different configurations. | |||
| ### Middleboxes | ### Middleboxes | |||
| <!--[rfced] How may we update this sentence to make it clear whether | ||||
| all the requirements or only some of the requirements require | ||||
| proxies to act as conforming TLS client and server? | ||||
| For background, in general, the RPC recommends using nonrestrictive "which" | ||||
| and restrictive "that". (More details are on | ||||
| https://www.rfc-editor.org/styleguide/tips/) However, edits to that | ||||
| usage have not been made in this document. In this specific sentence, | ||||
| we are asking about the usage because it can affect the understanding | ||||
| of the statement. | ||||
| Original: | ||||
| The requirements in [RFC8446], Section 9.3 which require proxies to | ||||
| act as conforming TLS client and server provide interoperability with | ||||
| TLS-terminating proxies even in cases where the server supports ECH | ||||
| but the proxy does not, as detailed below. | ||||
| Option A (all requirements require it): | ||||
| The requirements in [RFC8446], Section 9.3, which require proxies to | ||||
| act as conforming TLS client and server, provide interoperability with | ||||
| TLS-terminating proxies even in cases where the server supports ECH | ||||
| but the proxy does not, as detailed below. | ||||
| Option B (some requirements require it): | ||||
| The requirements in [RFC8446], Section 9.3 that require proxies to | ||||
| act as conforming TLS client and server provide interoperability with | ||||
| TLS-terminating proxies even in cases where the server supports ECH | ||||
| but the proxy does not, as detailed below. | ||||
| The requirements in {{RFC8446, Section 9.3}} which require proxies to | The requirements in {{RFC8446, Section 9.3}} which require proxies to | |||
| act as conforming TLS client and server provide interoperability | act as conforming TLS client and server provide interoperability | |||
| with TLS-terminating proxies even in cases where the server supports | with TLS-terminating proxies even in cases where the server supports | |||
| ECH but the proxy does not, as detailed below. | ECH but the proxy does not, as detailed below. | |||
| The proxy must ignore unknown parameters and | The proxy must ignore unknown parameters and | |||
| generate its own ClientHello containing only parameters it understands. Thus, | generate its own ClientHello containing only parameters it understands. Thus, | |||
| when presenting a certificate to the client or sending a ClientHello to the | when presenting a certificate to the client or sending a ClientHello to the | |||
| server, the proxy will act as if connecting to the ClientHelloOuter | server, the proxy will act as if connecting to the ClientHelloOuter | |||
| server_name, which SHOULD match the public name (see {{real-ech}}) without | server_name, which SHOULD match the public name (see {{real-ech}}) without | |||
| skipping to change at line 1526 ¶ | skipping to change at line 1479 ¶ | |||
| read packets from the network, but they cannot perform any sort of active | read packets from the network, but they cannot perform any sort of active | |||
| behavior such as probing servers or querying DNS. A middlebox that filters based | behavior such as probing servers or querying DNS. A middlebox that filters based | |||
| on plaintext packet contents is one example of a passive attacker. In contrast, | on plaintext packet contents is one example of a passive attacker. In contrast, | |||
| active attackers can also write packets into the network for malicious purposes, | active attackers can also write packets into the network for malicious purposes, | |||
| such as interfering with existing connections, probing servers, and querying | such as interfering with existing connections, probing servers, and querying | |||
| DNS. In short, an active attacker corresponds to the conventional threat model | DNS. In short, an active attacker corresponds to the conventional threat model | |||
| {{?RFC3552}} for TLS 1.3 {{RFC8446}}. | {{?RFC3552}} for TLS 1.3 {{RFC8446}}. | |||
| Passive and active attackers can exist anywhere in the network, including | Passive and active attackers can exist anywhere in the network, including | |||
| between the client and client-facing server, as well as between the | between the client and client-facing server, as well as between the | |||
| client-facing and backend servers when running ECH in Split Mode. However, | client-facing and backend servers when running ECH in split mode. However, | |||
| for Split Mode in particular, ECH makes two additional assumptions: | for split mode in particular, ECH makes two additional assumptions: | |||
| 1. The channel between each client-facing and each backend server is | 1. The channel between each client-facing and each backend server is | |||
| authenticated such that the backend server only accepts messages from trusted | authenticated such that the backend server only accepts messages from trusted | |||
| client-facing servers. The exact mechanism for establishing this authenticated | client-facing servers. The exact mechanism for establishing this authenticated | |||
| channel is out of scope for this document. | channel is out of scope for this document. | |||
| 1. The attacker cannot correlate messages between a client and client-facing | 1. The attacker cannot correlate messages between a client and client-facing | |||
| server with messages between client-facing and backend server. Such correlation | server with messages between client-facing and backend server. Such correlation | |||
| could allow an attacker to link information unique to a backend server, such as | could allow an attacker to link information unique to a backend server, such as | |||
| their server name or IP address, with a client's encrypted ClientHelloInner. | their server name or IP address, with a client's encrypted ClientHelloInner. | |||
| Correlation could occur through timing analysis of messages across the | Correlation could occur through timing analysis of messages across the | |||
| skipping to change at line 1721 ¶ | skipping to change at line 1674 ¶ | |||
| about the server identity. | about the server identity. | |||
| Backend servers in an anonymity set SHOULD NOT reveal information in the cookie | Backend servers in an anonymity set SHOULD NOT reveal information in the cookie | |||
| which identifies the server. This may be done by handling HelloRetryRequest | which identifies the server. This may be done by handling HelloRetryRequest | |||
| statefully, thus not sending cookies, or by using the same cookie construction | statefully, thus not sending cookies, or by using the same cookie construction | |||
| for all backend servers. | for all backend servers. | |||
| Note that, if the cookie includes a key name, analogous to {{Section 4 of | Note that, if the cookie includes a key name, analogous to {{Section 4 of | |||
| ?RFC5077}}, this may leak information if different backend servers issue | ?RFC5077}}, this may leak information if different backend servers issue | |||
| cookies with different key names at the time of the connection. In particular, | cookies with different key names at the time of the connection. In particular, | |||
| if the deployment operates in Split Mode, the backend servers may not share | if the deployment operates in split mode, the backend servers may not share | |||
| cookie encryption keys. Backend servers may mitigate this either by handling | cookie encryption keys. Backend servers may mitigate this either by handling | |||
| key rotation with trial decryption or by coordinating to match key names. | key rotation with trial decryption or by coordinating to match key names. | |||
| ## Attacks Exploiting Acceptance Confirmation | ## Attacks Exploiting Acceptance Confirmation | |||
| To signal acceptance, the backend server overwrites 8 bytes of its | To signal acceptance, the backend server overwrites 8 bytes of its | |||
| ServerHello.random with a value derived from the ClientHelloInner.random. (See | ServerHello.random with a value derived from the ClientHelloInner.random. (See | |||
| {{backend-server}} for details.) This behavior increases the likelihood of the | {{backend-server}} for details.) This behavior increases the likelihood of the | |||
| ServerHello.random colliding with the ServerHello.random of a previous session, | ServerHello.random colliding with the ServerHello.random of a previous session, | |||
| potentially reducing the overall security of the protocol. However, the | potentially reducing the overall security of the protocol. However, the | |||
| skipping to change at line 1842 ¶ | skipping to change at line 1795 ¶ | |||
| ### Maintain Forward Secrecy | ### Maintain Forward Secrecy | |||
| This design does not provide forward secrecy for the inner ClientHello | This design does not provide forward secrecy for the inner ClientHello | |||
| because the server's ECH key is static. However, the window of | because the server's ECH key is static. However, the window of | |||
| exposure is bound by the key lifetime. It is RECOMMENDED that servers | exposure is bound by the key lifetime. It is RECOMMENDED that servers | |||
| rotate keys regularly. | rotate keys regularly. | |||
| ### Enable Multi-party Security Contexts | ### Enable Multi-party Security Contexts | |||
| This design permits servers operating in Split Mode to forward connections | This design permits servers operating in split mode to forward connections | |||
| directly to backend origin servers. The client authenticates the identity of | directly to backend origin servers. The client authenticates the identity of | |||
| the backend origin server, thereby allowing the backend origin server | the backend origin server, thereby allowing the backend origin server | |||
| to hide behind the client-facing server without the client-facing | to hide behind the client-facing server without the client-facing | |||
| server decrypting and reencrypting the connection. | server decrypting and reencrypting the connection. | |||
| Conversely, if the DNS records used for configuration are | Conversely, if the DNS records used for configuration are | |||
| authenticated, e.g., via DNSSEC, | authenticated, e.g., via DNSSEC, | |||
| spoofing a client-facing server operating in Split Mode is not | spoofing a client-facing server operating in split mode is not | |||
| possible. See {{plaintext-dns}} for more details regarding plaintext | possible. See {{plaintext-dns}} for more details regarding plaintext | |||
| DNS. | DNS. | |||
| Authenticating the ECHConfig structure naturally authenticates the included | Authenticating the ECHConfig structure naturally authenticates the included | |||
| public name. This also authenticates any retry signals from the client-facing | public name. This also authenticates any retry signals from the client-facing | |||
| server because the client validates the server certificate against the public | server because the client validates the server certificate against the public | |||
| name before retrying. | name before retrying. | |||
| ### Support Multiple Protocols | ### Support Multiple Protocols | |||
| skipping to change at line 2048 ¶ | skipping to change at line 2001 ¶ | |||
| * If looking up a ClientHelloOuter extension takes time linear in the number of | * If looking up a ClientHelloOuter extension takes time linear in the number of | |||
| extensions, the overall decoding process would take O(M\*N) time, where | extensions, the overall decoding process would take O(M\*N) time, where | |||
| M is the number of extensions in ClientHelloOuter and N is the | M is the number of extensions in ClientHelloOuter and N is the | |||
| size of OuterExtensions. | size of OuterExtensions. | |||
| * If the same ClientHelloOuter extension can be copied multiple times, | * If the same ClientHelloOuter extension can be copied multiple times, | |||
| an attacker could cause the client-facing server to construct a large | an attacker could cause the client-facing server to construct a large | |||
| ClientHelloInner by including a large extension in ClientHelloOuter | ClientHelloInner by including a large extension in ClientHelloOuter | |||
| of length L and an OuterExtensions list referencing N copies of that | of length L and an OuterExtensions list referencing N copies of that | |||
| extension. The client-facing server would then use O(N\*L) memory in | extension. The client-facing server would then use O(N\*L) memory in | |||
| response to O(N+L) bandwidth from the client. In split-mode, an | response to O(N+L) bandwidth from the client. In split mode, an | |||
| O(N\*L)-sized packet would then be transmitted to the | O(N\*L)-sized packet would then be transmitted to the | |||
| backend server. | backend server. | |||
| ECH mitigates this attack by requiring that OuterExtensions be referenced in | ECH mitigates this attack by requiring that OuterExtensions be referenced in | |||
| order, that duplicate references be rejected, and by recommending that | order, that duplicate references be rejected, and by recommending that | |||
| client-facing servers use a linear scan to perform decompression. These | client-facing servers use a linear scan to perform decompression. These | |||
| requirements are detailed in {{encoding-inner}}. | requirements are detailed in {{encoding-inner}}. | |||
| # IANA Considerations | # IANA Considerations | |||
| skipping to change at line 2073 ¶ | skipping to change at line 2026 ¶ | |||
| 1. encrypted_client_hello (0xfe0d), with "TLS 1.3" column values set to | 1. encrypted_client_hello (0xfe0d), with "TLS 1.3" column values set to | |||
| "CH, HRR, EE", "DTLS-Only" column set to "N", and "Recommended" column set | "CH, HRR, EE", "DTLS-Only" column set to "N", and "Recommended" column set | |||
| to "Y". | to "Y". | |||
| 1. ech_outer_extensions (0xfd00), with the "TLS 1.3" column values set to "CH", | 1. ech_outer_extensions (0xfd00), with the "TLS 1.3" column values set to "CH", | |||
| "DTLS-Only" column set to "N", "Recommended" column set to "Y", and the | "DTLS-Only" column set to "N", "Recommended" column set to "Y", and the | |||
| "Comment" column set to "Only appears in inner CH." | "Comment" column set to "Only appears in inner CH." | |||
| ## Update of the TLS Alert Registry {#alerts} | ## Update of the TLS Alert Registry {#alerts} | |||
| IANA has created an entry, ech_required (121) in the existing "TLS Alerts" registry ( | IANA has created an entry, ech_required (121) in the existing "TLS | |||
| defined in {{!RFC8446}}), with the "DTLS-OK" column set to | Alerts" registry (defined in {{!RFC8446}}), with the "DTLS-OK" column | |||
| "Y". | set to "Y". | |||
| ## ECH Configuration Extension Registry {#config-extensions-iana} | ## ECH Configuration Extension Registry {#config-extensions-iana} | |||
| IANA has created a new "TLS ECHConfig Extension" registry in a new | IANA has created a new "TLS ECHConfig Extension" registry in a new | |||
| "TLS Encrypted Client Hello (ECH) Configuration Extensions" registry group. New | "TLS Encrypted Client Hello (ECH) Configuration Extensions" registry group. New | |||
| registrations will list the following attributes: | registrations will list the following attributes: | |||
| Value: | Value: | |||
| : The two-byte identifier for the ECHConfigExtension, i.e., the | : The two-byte identifier for the ECHConfigExtension, i.e., the | |||
| ECHConfigExtensionType | ECHConfigExtensionType | |||
| skipping to change at line 2136 ¶ | skipping to change at line 2090 ¶ | |||
| Extension Name: | Extension Name: | |||
| : RESERVED | : RESERVED | |||
| Recommended: | Recommended: | |||
| : Y | : Y | |||
| Reference: | Reference: | |||
| : RFC 9849 | : RFC 9849 | |||
| Notes: | Notes: | |||
| : Grease entries | : GREASE entries | |||
| {: spacing="compact"} | {: spacing="compact"} | |||
| <!-- [rfced] We note that the following terms use fixed-width font | <!-- [rfced] We note that the following terms use fixed-width font | |||
| inconsistently. Please review these terms and let us know how we should update | inconsistently. Please review these terms and let us know how we should update | |||
| or if there are any specific patterns that should be followed (e.g., | or if there are any specific patterns that should be followed (e.g., | |||
| fixed-width font used for field names, variants, etc.). | fixed-width font used for field names, variants, etc.). | |||
| accept_confirmation | accept_confirmation | |||
| cipher_suite | cipher_suite | |||
| ClientHello | ClientHello | |||
| skipping to change at line 2164 ¶ | skipping to change at line 2118 ¶ | |||
| ECHConfigContents | ECHConfigContents | |||
| ECHConfigList | ECHConfigList | |||
| EncodedClientHelloInner | EncodedClientHelloInner | |||
| inner | inner | |||
| maximum_name_length | maximum_name_length | |||
| outer | outer | |||
| payload | payload | |||
| public_key | public_key | |||
| ServerHello.random | ServerHello.random | |||
| zeros | zeros | |||
| <!-- [rfced] We note that these terms are used inconsistently. Please let us | EKR: Thanks. Fixed width should be used for field names and other PDUs. | |||
| know which form you prefer. | ||||
| split-mode vs. Split Mode | I notice that some of these are regular words (zeros) so you have to determine from c | |||
| GREASE vs. Grease (IANA Section) | ontext whether it's referring to some protocol element or just to the concept "carrie | |||
| s an encrypted payload" versus "the payload field". Do you want to take a cut at chan | ||||
| ging as many of these as make sense and then I can review, or would you prefer I make | ||||
| the changes? | ||||
| <!-- [rfced] FYI - We have added expansions for abbreviations upon first use | One question is what to do in definition lists. My sense is that the list heds should | |||
| per Section 3.6 of RFC 7322 ("RFC Style Guide"). Please review each | be non-fixed-width but maybe you have a convention. | |||
| expansion in the document carefully to ensure correctness. | ||||
| <!-- [rfced] Please review the "Inclusive Language" portion of the online | rfced: Thank you for offering to make changes. Please feel free to attach an updated | |||
| Style Guide <https://www.rfc-editor.org/styleguide/part2/#inclusive_language> | markdown file containing the | |||
| and let us know if any changes are needed. Updates of this nature typically | updates for terms using fixed-width font. | |||
| result in more precise language, which is helpful for readers. Note that our | ||||
| script did not flag any words in particular, but this should still be reviewed | For definition lists, we typically leave this up to the authors to determine how they | |||
| as a best practice. --> | would like the terms to appear for consistency. For an example of terms in a definit | |||
| ion list using a fixed-width font, see: https://www.rfc-editor.org/rfc/rfc9623.html#s | ||||
| ection-5.1.1. | ||||
| --> | ||||
| -> | ||||
| --- back | --- back | |||
| # Linear-Time Outer Extension Processing {#linear-outer-extensions} | # Linear-Time Outer Extension Processing {#linear-outer-extensions} | |||
| The following procedure processes the "ech_outer_extensions" extension (see | The following procedure processes the "ech_outer_extensions" extension (see | |||
| {{encoding-inner}}) in linear time, ensuring that each referenced extension | {{encoding-inner}}) in linear time, ensuring that each referenced extension | |||
| in the ClientHelloOuter is included at most once: | in the ClientHelloOuter is included at most once: | |||
| 1. Let I be initialized to zero and N be set to the number of extensions | 1. Let I be initialized to zero and N be set to the number of extensions | |||
| End of changes. 29 change blocks. | ||||
| 111 lines changed or deleted | 69 lines changed or added | |||
This html diff was produced by rfcdiff 1.48. | ||||