<?xml version="1.0" encoding="US-ASCII"?>
<!-- this is version 5 of this xml2rfc template -->
<!DOCTYPE rfc SYSTEM "rfc2629.dtd" [
<!ENTITY rfc2119 SYSTEM "https://xml.resource.org/public/rfc/bibxml/reference.RFC.2119.xml">
<!ENTITY rfc8174 SYSTEM "https://xml.resource.org/public/rfc/bibxml/reference.RFC.8174.xml">
<!ENTITY rfc8446 SYSTEM "https://xml.resource.org/public/rfc/bibxml/reference.RFC.8446.xml">
<!ENTITY rfc8615 SYSTEM "https://xml.resource.org/public/rfc/bibxml/reference.RFC.8615.xml">
<!ENTITY I-D.ietf-tls-esni SYSTEM "http://xml.resource.org/public/rfc/bibxml3/reference.I-D.ietf-tls-esni">
<!ENTITY I-D.ietf-dnsop-svcb-https SYSTEM "http://xml.resource.org/public/rfc/bibxml3/reference.I-D.ietf-dnsop-svcb-https">

]>
<?rfc toc="yes"?>
<?rfc symrefs="yes"?>
<?rfc compact="yes"?>
<?rfc subcompact="yes"?>
<?rfc strict="no"?>
<?rfc rfcedstyle="yes"?>
<?rfc comments="yes"?>
<?rfc inline="yes"?>
<rfc category="exp" docName="draft-ietf-tls-wkech-01" ipr="trust200902" >
  <front>
    <title abbrev="Well-Known URI for ECH">A well-known URI for publishing ECHConfigList values.</title>

    <author fullname="Stephen Farrell" initials="S." surname="Farrell">
      <organization>Trinity College Dublin</organization>

      <address>
        <postal>
          <street/>

          <city>Dublin</city>

          <region/>

          <code>2</code>

          <country>Ireland</country>
        </postal>

        <phone>+353-1-896-2354</phone>

        <email>stephen.farrell@cs.tcd.ie</email>
      </address>
    </author>

    <author initials="R." surname="Salz" fullname="Rich Salz">
        <organization>Akamai Technologies</organization>
        <address>
            <email>rsalz@akamai.com</email>
        </address>
    </author>

    <author initials="B." surname="Schwartz" fullname="Benjamin Schwartz">
      <organization>Google LLC</organization>
      <address>
        <email>bemasc@google.com</email>
      </address>
    </author>

    <date year="2022"/>

    <area>Security Area</area>

    <workgroup>TLS</workgroup>

    <keyword>TLS</keyword>

    <keyword>ECH</keyword>

    <abstract>
        <t>
            We propose use of a well-known URI at which an HTTP origin can
            inform an authoritative DNS server, or other interested parties,
            about this origin's Service Bindings, i.e. its "HTTPS" DNS records.
            These instructions can include Encrypted ClientHello (ECH)
            configurations, allowing the origin to publish and rotate its own
            ECH keys.
        </t>

        <t>
            AUTHORS NOTE: This
            version proposes changing from the highly ECHConfig specific
            approach of -00 to a much more generic approach.  The authors
            are seeking feedback from the Working Group as
            to which of these approaches may be more likely to garner
            rough consensus.  If the WG feel this is worse than
            -00 we're fine with reverting.
        </t>
    </abstract>
  </front>

  <middle>
    <section title="Introduction">

        <t>Encrypted ClientHello (ECH) 
            <xref target="I-D.ietf-tls-esni"/> for TLS1.3 <xref target="RFC8446"/>
            defines a confidentiality mechanism for server names and other ClientHello content in TLS.
            For many applications, that requires publication of ECHConflgList data structures in the DNS.
            An ECHConfigList structure contains a list of ECHConfig values. Each
            ECHConfig value contains the public component of a key pair
            that will typically be periodically (re-)generated by a web server.
            Many web infrastructures will have an API that can be used to 
            dynamically update the DNS RR values containing ECHConfigList values. 
            Some deployments however, will not, so web deployments could 
            benefit from a mechanism to use in such cases. 
        </t>

        <t>
            We define such a mechanism here. Note that this is not intended for
            universal deployment, but rather for cases where the web server
            doesn't have write access to the relevant zone file (or 
            equivalent). That zone file will eventually include an HTTPS or SVCB 
            RR <xref target="I-D.ietf-dnsop-svcb-https"/> containing an ECHConfigList.
            This mechanism is extensible to deliver other kinds of information about
            the origin, but in this specification it only provides the functionality
            necessary to configure ECH.
        </t>

        <t>
            We use the term "zone factory" for the entity that does have write
            access to the zone file. We assume the zone factory (ZF) can also 
            make HTTPS requests to the web server with the ECH keys.
        </t>

        <t>
            We propose use of a well-known URI <xref target="RFC8615"/> on the web server that 
            allows ZF to poll for changes to ECHConfigList values. For example, if a web server 
            generates new ECHConfigList values hourly and publishes those at the well-known URI, 
            ZF can poll that URI.  When ZF sees new values, it can check if those work, and if 
            they do, then update the zone file and re-publish the zone.
        </t>

        <t>[[The source for this is in https://github.com/sftcd/wkesni/ 
            PRs are welcome there too.]]
        </t>

      </section>

      <section title="Terminology">
        <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 target="RFC8174"/> when, and only
        when, they appear in all capitals, as shown here.</t>
      </section>

    <section title="Example use of the well-known URI for ECH">

        <t>An example deployment could be as follows:

           <list style="numbers">
                <t> Web server generates new ECHConfigList values hourly at N past 
                    the hour via some regular, automated process (e.g. a cronjob)</t>
                <t> ECHConfigList values are "current" for an hour, and remain usable
                    for 3 hours from the time of generation</t>
                <t> The cronjob updates the ECHConfigList values in a JSON resource at
                    at https://$ORIGIN/.well-known/origin-svcb, as shown in 
                    <xref target="sample-json"/>.</t>
                <t> On the zone factory, an HTTP client retrieves this JSON resource.
                    It attempts to connect to the origin using these values and confirms
                    that they are working.</t>
                <t> The zone factory observes that the JSON resource
                    has an HTTP freshness lifetime of 3600 seconds, and chooses a DNS
                    TTL of 1800.  It updates the zone file for $ORIGIN and re-publishes
                    the zone containing only the new ECHConfigList values.</t>
                <t> When the TTL of the DNS records approaches the remaining freshness
                    lifetime of the JSON resource, the zone factory attempts to refresh
                    its cached copy of the JSON resource.  If the resource has changed,
                    it repeats this process.</t>
            </list>
        </t>

    </section>

    <section title="The origin-svcb well-known URI">

         <t>
            If a web server ($ORIGIN) wants to convey information to the Zone
            Factory, it publishes the JSON content
            defined in <xref target="jsonstr"/> at:
            https://$ORIGIN/.well-known/origin-svcb
        </t>

        <t>The well-known URI defined here MUST be an https URL and therefore the
            zone factory verifies the correct $ORIGIN is being accessed. If
            there is any failure in accessing the well-known URI, then the
            zone factory MUST NOT modify the zone. </t> 

    </section>


<section anchor="jsonstr" title="The JSON structure for origin service binding info">

  <t>[[The JSON structure is a work in progress.]]</t>

<figure anchor="sample-json" title="Sample JSON for ECH without aliases" >
<artwork><![CDATA[
    {
        "endpoints": [{
            "priority": 1,
            "target": "cdn.example.",
            "ech": "AD7+DQA65wAgAC..AA=="
        }, {
            "priority": 1,
            "port": 8413,
            "ech": "AD7+DQA65wAgAC..AA=="
        }]
    }
  ]]></artwork>
</figure>

<figure anchor="sample-json-alias" title="Sample JSON with aliasing" >
    <artwork><![CDATA[
        {
            "alias": "cdn.example.net:443"
        }
    ]]></artwork>
</figure>

    <t>
        The JSON file at the well-known URI MUST contain an object
        with either an "endpoints" key or an "alias" key.  If the
        "endpoints" key is present, its value is an array whose elements
        represent HTTPS records in ServiceMode. Each element MAY contain
        one or more keys from the JSON HTTP Origin Info registry (see
        IANA Considerations).  The initial registry entries are:
        <list style="symbols">
            <t>
                priority: The value is a positive integer corresponding to the
                SvcPriority.  If omitted, the zone factory SHOULD infer
                numerically increasing SvcPriority from the order of the
                endpoints array.
            </t>
            <t>
                target: The value is a string containing a fully qualified
                domain name, corresponding to the HTTPS record's TargetName.
                The default value is ".".
            </t>
            <t>
                port: The value is a non-negative integer, corresponding to
                the value of the "port" SvcParamKey.
            </t>
            <t>
                ech: The value is a string containing an ECHConfigList encoded
                in Base64 <xref target="RFC4648"/>, corresponding to the value
                of the "ech" SvcParamKey.
            </t>
        </list>
        An empty endpoint object corresponds to an HTTPS record with inferred
        SvcPriority, TargetName=".", and no ECH support.  An empty record of
        this kind can be useful as a simple way to make use of the HTTPS RR
        type's HSTS behavior.
    </t>

    <t>
        [[TODO: What does the zone factory do if it encounters an unrecognized
        field?]]
    </t>

    <t>
        If the object contains an "alias" key, its value MUST be an "authority"
        (Section 3.2 of <xref target="RFC3986"/>).  This indicates that $ORIGIN
        is hosted on the same endpoints as this target, and is equivalent to
        an HTTPS AliasMode record.  A zone factory might implement this directive
        by publishing an AliasMode record, publishing a CNAME record, copying
        HTTPS records from the target zone, or fetching
        https://$TARGET/.well-known/origin-svcb" (if it exists).
    </t>

    <t>
        This arrangement provides the following important properties:
        <list style="symbols">
            <t>
                Origins can indicate that different ECHConfigs are used on
                different ports.
            </t>
            <t>
                Origins can indicate that multiple CDNs are in use, each with
                its own ECHConfig.
            </t>
            <t>
                Origins that simply alias to a single target can indicate this
                without copying the ECHConfig and other parameters, which
                can interfere with key rotation and other maintenance.
            </t>
            <t>
                "port" and "target" are generally sufficient to uniquely identify
                a ServiceMode record, so zone factories can use the endpoint list
                to add ECH to pre-existing ServiceMode records that may have other
                SvcParams.
            </t>
        </list>
    </t>

</section>

<section title="Zone factory behaviour">

    <t>The zone factory SHOULD check that the presented endpoints
        work and provide access to $ORIGIN before publication.
        A bespoke TLS client may be needed for this check,
        that does not require the ECHConfigList value to have 
        already been published in the DNS.
        [[I guess that calls for the zone factory to know
        of a "safe" URL on $ORIGIN to try, or maybe it could
        use HTTP HEAD? Figuring that out is TBD. The ZF could also
        try a GREASEd ECH and see if the retry-configs it gets back
        is one of the ECHConfig values in the ECHConfigList.]]
    </t>

    <t>A careful zone factory could explode the ECHConfigList value
       presented into "singleton" values with one public key in each
       and test each for each endpoint.</t>

    <t>The zone factory SHOULD publish all the endpoints
        that are presented in the JSON file, and that pass
        the check above.</t>

    <t>The zone factory MUST set a DNS TTL short enough that any
        generated records expire from DNS caches before the JSON
        object's HTTP cache lifetime expires.  The zone factory
        MUST refresh the JSON object and regenerate the zone
        before it expires each time.  This ensures that ECHConfigs
        are not used longer than intended by the origin, while
        permitting the zone factory to limit the TTL if desired.
    </t>

</section>


    <section title="Security Considerations">
        <t>This document defines another way to publish ECHConfigList values. If the wrong
            keys were read from here and published in the DNS, then clients
            using ECH would do the wrong thing, likely resulting in 
            denial of service, or a privacy leak, or worse, when TLS clients attempt to use ECH with
            a backend web site. So: Don't do that:-)</t>

        <t>
            Although this configuration resource MAY be publicly
            accessible, general HTTP clients SHOULD NOT attempt to use this
            resource in lieu of HTTPS records queries through their preferred
            DNS server:
            <list style="symbols">
                <t>
                    The bootstrap connection would not be able to use ECH,
                    so it would reveal all the information that ECH seeks
                    to protect.
                </t>
                <t>
                    The origin could serve the user with a uniquely
                    identifying configuration, potentially resulting in an
                    unexpected tracking vector.
                </t>
            </list>
        </t>
             
    </section>

    <section title="Acknowledgements">
        <t>Thanks to Niall O'Reilly for a quick review of -00.</t>
    </section>

    <section title="IANA Considerations">
        <t>[[TBD: IANA registration of a .well-known. Also TBD - how to handle I18N for
            $FRONT and $BACKEND within such a URL.]]</t>

        <t>If approved, this specification requests the creation of an IANA
            registry named "JSON HTTP Origin Info" with a Standards Action
            registration policy, containing a field named "Name"
            whose value is a UTF-8 string.
        </t>

    </section>
  </middle>

  <back>
    <references title="Normative References">
      <?rfc include='reference.RFC.2119'?>
      <?rfc include='reference.RFC.8174'?>
      <?rfc include='reference.RFC.8446'?>
      <?rfc include='reference.RFC.8615'?>
      <?rfc include='reference.RFC.3986'?>
      <?rfc include='reference.RFC.4648'?>
      &I-D.ietf-tls-esni;
      &I-D.ietf-dnsop-svcb-https;

    </references>

    <!--
    <references title="Informative References">
    </references>
    -->

    <section title="Change Log ">
      <t>[[RFC editor: please remove this before publication.]]</t>

      <t>The -00 WG draft replaces draft-farrell-tls-wkesni-03.</t>

      <t>
        Version 01 changed from a special-purpose design, carrying only
        ECHConfigs and port numbers, to a more general approach based on
        Service Bindings.
      </t>

    </section>
  </back>
</rfc>
