<?xml version="1.0"encoding="us-ascii"?>encoding="UTF-8"?> <!DOCTYPE rfc SYSTEM"rfc2629.dtd" [ <!ENTITY RFC2119 SYSTEM "http://www.rfc-editor.org/refs/bibxml/reference.RFC.2119.xml"> <!ENTITY RFC3610 SYSTEM "http://www.rfc-editor.org/refs/bibxml/reference.RFC.3610.xml"> <!ENTITY RFC4107 SYSTEM "http://www.rfc-editor.org/refs/bibxml/reference.RFC.4107.xml"> <!ENTITY RFC6234 SYSTEM "http://www.rfc-editor.org/refs/bibxml/reference.RFC.6234.xml"> <!ENTITY RFC7228 SYSTEM "http://www.rfc-editor.org/refs/bibxml/reference.RFC.7228.xml"> <!ENTITY RFC7252 SYSTEM "http://www.rfc-editor.org/refs/bibxml/reference.RFC.7252.xml"> <!ENTITY RFC7641 SYSTEM "http://www.rfc-editor.org/refs/bibxml/reference.RFC.7641.xml"> <!ENTITY RFC7959 SYSTEM "http://www.rfc-editor.org/refs/bibxml/reference.RFC.7959.xml"> <!ENTITY RFC8174 SYSTEM "http://www.rfc-editor.org/refs/bibxml/reference.RFC.8174.xml"> <!ENTITY RFC8323 SYSTEM "http://www.rfc-editor.org/refs/bibxml/reference.RFC.8323.xml"> <!ENTITY I-D.ietf-6tisch-minimal-security SYSTEM "http://www.rfc-editor.org/refs/bibxml3/reference.I-D.ietf-6tisch-minimal-security.xml"> <!ENTITY I-D.ietf-core-echo-request-tag SYSTEM "http://www.rfc-editor.org/refs/bibxml3/reference.I-D.ietf-core-echo-request-tag.xml"> ]> <?xml-stylesheet type="text/xsl" href="rfc2629.xslt"?> <?rfc compact="yes"?> <?rfc sortrefs="yes"?> <?rfc subcompact="no"?> <?rfc symrefs="yes"?> <?rfc toc="yes"?> <?rfc tocdepth="3"?>"rfc2629-xhtml.ent"> <rfccategory="std"xmlns:xi="http://www.w3.org/2001/XInclude" docName="draft-ietf-core-stateless-08" number="8974" ipr="trust200902" updates="7252,8323">8323" obsoletes="" submissionType="IETF" category="std" consensus="true" xml:lang="en" sortRefs="true" symRefs="true" tocInclude="true" tocDepth="3" version="3"> <!-- xml2rfc v2v3 conversion 3.5.0 --> <front> <title abbrev="Extended Tokens in CoAP">Extended Tokens and Stateless Clients in the Constrained Application Protocol (CoAP)Extended Tokens and Stateless Clients in the Constrained Application Protocol (CoAP) </title> <seriesInfo name="RFC" value="8974"/> <author initials="K." surname="Hartke" fullname="Klaus Hartke"> <organization>Ericsson</organization> <address> <postal> <street>Torshamnsgatan 23</street> <city>Stockholm</city><code>SE-16483</code><code>16483</code> <country>Sweden</country> </postal> <email>klaus.hartke@ericsson.com</email> </address> </author> <author fullname="Michael C. Richardson" initials="M." surname="Richardson"> <organization abbrev="Sandelman">Sandelman Software Works</organization> <address> <email>mcr+ietf@sandelman.ca</email> <uri>http://www.sandelman.ca/</uri> </address> </author><date/><date year="2021" month="January" /> <workgroup>CoRE Working Group</workgroup> <abstract> <t> This document provides considerations for alleviatingCoAPConstrained Application Protocol (CoAP) clients and intermediaries of keeping per-request state. To facilitate this, this document additionally introduces a new, optional CoAP protocol extension for extended token lengths. </t> <t> This document updates RFCs 7252 and 8323 with an extended definition of theTKL"TKL" field in the CoAP message header. </t> </abstract> </front> <middle><!-- **************************************************************** --> <!-- **************************************************************** --> <!-- **************************************************************** --> <!-- **************************************************************** --><sectiontitle="Introduction" anchor="introduction">anchor="introduction" numbered="true" toc="default"> <name>Introduction</name> <t> The Constrained Application Protocol (CoAP) <xreftarget="RFC7252"/>target="RFC7252" format="default"/> is a RESTful application-layer protocol for <xreftarget="RFC7228">constrainedtarget="RFC7228" format="default">constrained environments</xref>. In CoAP, clients (or intermediaries in the client role) make requests to servers (or intermediaries in the server role), which satisfy the requests by returning responses. </t> <t> While a request is ongoing, a client typically needs to keep some state that it requires for processing the response when that arrives. Identification of this state is done in CoAP by means of atoken,token: an opaque sequence of bytes that is chosen by the client and included in the CoAPrequest,request and that is returned by the server verbatim in any resulting CoAP response (<xreftarget="stateful-exchange"/>).target="stateful-exchange" format="default"/>). </t> <figureanchor="stateful-exchange" title="Tokenanchor="stateful-exchange"> <name>Token as an Identifier for RequestState"><artwork align="center"><![CDATA[State</name> <artwork align="center" name="" type="" alt=""><![CDATA[ +-----------------+ request with +------------+ | | | state identifier | | | | | as token | | | .-<-+->------|--------------------->|------. | | _|_ | | | | | / \ stored | | | | | \___/ state | | | | | | | | | | | '->-+-<------|<---------------------|------' | | | | response with | | | v | token echoed back | | +-----------------+ +------------+ Client Server]]></artwork></figure>]]></artwork> </figure> <t> In some scenarios, it can be beneficial to reduce the amount of state that is stored at the client at the cost of increased message sizes. A client can opt into this by serializing (parts of) its state into the token itself and then recovering this state from the token in the response (<xreftarget="stateless-exchange"/>).target="stateless-exchange" format="default"/>). </t> <figureanchor="stateless-exchange" title="Tokenanchor="stateless-exchange"> <name>Token as Serialization of RequestState"><artwork align="center"><![CDATA[State</name> <artwork align="center" name="" type="" alt=""><![CDATA[ +-----------------+ request with +------------+ | | | serialized state | | | | | as token | | | +--------|=====================>|------. | | | | | | | look ma, | | | | | no state! | | | | | | | | | | +--------|<=====================|------' | | | | response with | | | v | token echoed back | | +-----------------+ +------------+ Client Server]]></artwork></figure>]]></artwork> </figure> <t> <xreftarget="stateless-clients"/>target="stateless-clients" format="default"/> of this document provides considerations for clients becoming "stateless" in this way. (The term "stateless" is in quotes here, because it's a bit oversimplified. Such clients still need to maintain per-server state and other kinds of state. So it would be more accurate to just say that the clients are avoiding per-request state.) </t> <t> <xreftarget="stateless-intermediaries"/>target="stateless-intermediaries" format="default"/> of this document extends the considerations for clients to intermediaries, which maynot onlywant to avoid keeping state for not only the requests they send to servers but alsoforthe requests they receive from clients. </t> <t> The serialization of state into tokens is limited by the fact that both <xreftarget="RFC7252">CoAPtarget="RFC7252" format="default">CoAP over UDP</xref> and <xreftarget="RFC8323">CoAPtarget="RFC8323" format="default">CoAP over reliable transports</xref> restrict the maximum token length to 8 bytes. To overcome this limitation, <xreftarget="extended-tokens"/>target="extended-tokens" format="default"/> of this documentfirstintroduces a CoAP protocol extension for extended token lengths. </t> <t> While the use case (avoiding per-request state) and the mechanism (extended token lengths) presented in this document are closely related,botheach can be used independently ofeach other:the other. Some implementations may be able to fit their state in just 8 bytes; some implementations may have other use cases for extended token lengths. </t> <sectiontitle="Terminology">numbered="true" toc="default"> <name>Terminology</name> <t> In this document, the term "stateless" refers to an implementation strategy for a client (or intermediary in the client role) that does not require it to keep state for the individual requests it sends to a server (or intermediary in the server role). The client still needs to keep state for each server it communicates with (e.g., for token generation, message retransmission, and congestion control). </t> <t> The key words"MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY","<bcp14>MUST</bcp14>", "<bcp14>MUST NOT</bcp14>", "<bcp14>REQUIRED</bcp14>", "<bcp14>SHALL</bcp14>", "<bcp14>SHALL NOT</bcp14>", "<bcp14>SHOULD</bcp14>", "<bcp14>SHOULD NOT</bcp14>", "<bcp14>RECOMMENDED</bcp14>", "<bcp14>NOT RECOMMENDED</bcp14>", "<bcp14>MAY</bcp14>", and"OPTIONAL""<bcp14>OPTIONAL</bcp14>" in this document are to be interpreted as described in BCP 14 <xreftarget="RFC2119">BCP 14</xref>target="RFC2119"/> <xref target="RFC8174"/> when, and only when, they appear in all capitals, as shown here. </t> </section> </section><!-- **************************************************************** --> <!-- **************************************************************** --> <!-- **************************************************************** --> <!-- **************************************************************** --><sectiontitle="Extended Tokens" anchor="extended-tokens">anchor="extended-tokens" numbered="true" toc="default"> <name>Extended Tokens</name> <t> This document updates the message formats defined for <xreftarget="RFC7252">CoAPtarget="RFC7252" format="default">CoAP over UDP</xref> and <xreftarget="RFC8323">CoAPtarget="RFC8323" format="default">CoAP over TCP, TLS, and WebSockets</xref> with a new definition of theTKL"TKL" field. </t> <sectiontitle="Extendedanchor="tkl-field" numbered="true" toc="default"> <name>Extended Token Length (TKL)Field" anchor="tkl-field">Field</name> <t> The definition of theTKL"TKL" field is updated as follows:<list style="hanging"> <t hangText="Token</t> <dl newline="false" spacing="normal"> <dt>Token Length(TKL):">(TKL):</dt> <dd> <t> 4-bit unsigned integer. A value between 0 and12 inclusive12, inclusive, indicates the length of the variable-lengthToken"Token" field in bytes. The other three values are reserved for special constructs:<list style="hanging"> <t hangText="13:"></t> <dl newline="false" spacing="normal" indent="6"> <dt>13:</dt> <dd> An 8-bit unsigned integer directly precedes theToken"Token" field and indicates the length of theToken"Token" field minus 13.</t> <t hangText="14:"></dd> <dt>14:</dt> <dd> A 16-bit unsigned integer in network byte order directly precedes theToken"Token" field and indicates the length of theToken"Token" field minus 269.</t> <t hangText="15:"></dd> <dt>15:</dt> <dd> Reserved. This valueMUST NOT<bcp14>MUST NOT</bcp14> be sent andMUST<bcp14>MUST</bcp14> be processed as amessage formatmessage-format error.</t> </list> </t> </list> </t></dd> </dl> </dd> </dl> <t> All other fields retain their definitions. </t> <t> The updated message formats are illustrated in <xreftarget="message-formats"/>.target="message-formats" format="default"/>. </t> <t> The new definition of theTKL"TKL" field increases the maximum token length that can be represented in a message to 65804 bytes. However, the maximum token length that sender and recipient implementations support may be shorter. For example, a constrained node of <xreftarget="RFC7228">Classtarget="RFC7228" format="default">Class 1</xref> might support extended token lengths only up to 32 bytes. </t> <t> In CoAP over UDP, it is often beneficial to keep CoAP messages small enough to avoid IP fragmentation. The maximum practical token length may therefore also be influenced by the PathMTU.MTU (PMTU). SeeSection 4.6 of RFC 7252<xref target="RFC7252" sectionFormat="of" section="4.6" /> for details. </t> </section> <sectiontitle="Discovering Support" anchor="discovery">anchor="discovery" numbered="true" toc="default"> <name>Discovering Support</name> <t> Extended token lengths require support from server implementations. Support can be discovered by a client implementation in one of two ways:<list style="symbols"> <t></t> <ul spacing="normal"> <li> Where Capabilities and Settings Messages (CSMs) are available, such as in CoAP over TCP, support can be discovered using the Extended-Token-Length Capability Option defined in <xreftarget="capability-option"/>. </t> <t>target="capability-option" format="default"/>. </li> <li> Otherwise, such as in CoAP over UDP, support can only be discovered bytrial-and-error,trial and error, as described in <xreftarget="trial-and-error"/>. </t> </list> </t>target="trial-and-error" format="default"/>. </li> </ul> <sectiontitle="Extended-Token-Lengthanchor="capability-option" numbered="true" toc="default"> <name>Extended-Token-Length CapabilityOption" anchor="capability-option">Option</name> <t> A server can use the elective Extended-Token-Length Capability Option to indicate the maximum token length it can accept in requests. </t><texttable title="The<table anchor="capability-option-definition" align="center"> <name>The Extended-Token-Length CapabilityOption" anchor="capability-option-definition"> <ttcol align="right">#</ttcol> <ttcol align="left">C</ttcol> <ttcol align="left">R</ttcol> <ttcolOption</name> <thead> <tr> <th align="right">#</th> <th align="left">C</th> <th align="left">R</th> <th align="left">Appliesto</ttcol> <ttcol align="left">Name</ttcol> <ttcol align="left">Format</ttcol> <ttcol align="left">Length</ttcol> <ttcolto</th> <th align="left">Name</th> <th align="left">Format</th> <th align="left">Length</th> <th align="left">BaseValue</ttcol> <c>TBD</c> <c></c> <c></c> <c>CSM</c> <c>Extended-Token-Length</c> <c>uint</c> <c>0-3</c> <c>8</c> <postamble>C=Critical, R=Repeatable</postamble> </texttable>Value</th> </tr> </thead> <tbody> <tr> <td align="right">6</td> <td align="left"/> <td align="left"/> <td align="left">CSM</td> <td align="left">Extended-Token-Length</td> <td align="left">uint</td> <td align="left">0-3</td> <td align="left">8</td> </tr> </tbody> </table> <t keepWithPrevious="true">C=Critical, R=Repeatable</t> <t> As perSection 3 of RFC 7252,<xref target="RFC7252" sectionFormat="of" section="3" />, the base value (and the value used when this option is not implemented) is 8. </t> <t> The active value of the Extended-Token-Length Option is replaced each time the option is sent with a modified value. Its starting value is its base value. </t> <t> The option valueMUST NOT<bcp14>MUST NOT</bcp14> be less than 8 or greater than 65804. If an option value less than 8 is received, the optionMUST<bcp14>MUST</bcp14> be ignored. If an option value greater than 65804 is received, the option valueMUST<bcp14>MUST</bcp14> be set to 65804. </t> <t> Any option value greater than 8 implies support for the new definition of theTKL"TKL" field specified in <xreftarget="tkl-field"/>.target="tkl-field" format="default"/>. Indication of support by a server does not oblige a client to actually make use of token lengths greater than 8. </t> <t> If a server receives a request with a token of a length greater than what it indicated in its Extended-Token-Length Option, itMUST<bcp14>MUST</bcp14> handle the request as amessage formatmessage-format error. </t> <t> If a server receives a request with a token of a length lessthanthan, or equaltoto, what it indicated in its Extended-Token-Length Option but is unwilling or unable to handle the token at that time, itMUST NOT<bcp14>MUST NOT</bcp14> handle the request as amessage formatmessage-format error. Instead, itSHOULD<bcp14>SHOULD</bcp14> return a 5.03 (Service Unavailable) response. </t> <t> The Extended-Token-Length Capability Option does not apply to responses. The sender of a request is simply expected not to use a token of a length greater than it is willing to accept in a response. </t> </section> <sectiontitle="Trial-and-Error" anchor="trial-and-error">anchor="trial-and-error" numbered="true" toc="default"> <name>Trial and Error</name> <t> A server implementation that does not support the updated definition of theTKL"TKL" field specified in <xreftarget="tkl-field"/>target="tkl-field" format="default"/> will consider a request with aTKL"TKL" field value outside the range 0 to 8 to be amessage formatmessage-format error and reject it(Section 3 of RFC 7252).(<xref target="RFC7252" sectionFormat="of" section="3" />). A client can therefore determine support by sending a request with an extended token length and checking whether or not it is rejected by theserver or not.server. </t> <t> In CoAP over UDP, the way a request message is rejected depends on the message type. A Confirmable message with amessage formatmessage-format error is rejected with a Reset message(Section 4.2 of RFC 7252).(<xref target="RFC7252" sectionFormat="of" section="4.2" />). A Non-confirmable message with amessage formatmessage-format error is either rejected with a Reset message or just silently ignored(Section 4.3 of RFC 7252).(<xref target="RFC7252" sectionFormat="of" section="4.3" />). To reliably get a Reset message, it is thereforeREQUIRED<bcp14>REQUIRED</bcp14> that clients use a Confirmable message for determining support. </t> <t> As per RFC 7252, Reset messages are empty and do not contain a token; they only return the Message ID (<xreftarget="trial-and-error-illustration"/>).target="trial-and-error-illustration" format="default"/>). They also do not contain any indication of what caused amessage formatmessage-format error. To avoid any ambiguity, it is thereforeRECOMMENDED<bcp14>RECOMMENDED</bcp14> that clients use a request that has no potentialmessage formatmessage-format error other than the extended token length. </t> <figureanchor="trial-and-error-illustration" title="Aanchor="trial-and-error-illustration"> <name>A Confirmable RequestWithwith an Extended TokenisIs RejectedWithwith a Reset MessageifIf the Server Does Not HaveSupport"><artwork align="center"><![CDATA[Support</name> <artwork align="center" name="" type="" alt=""><![CDATA[ +-----------------+ request message +------------+ | | | with extended | | | | | token length | | | .-<-+->------|--------------------->|------. | | _|_ | | | | | / \ stored | | | | | \___/ state | | | | | | | | | | | '->-+-<------|<---------------------|------' | | | |resetReset message | | | v | with only message | | +-----------------+ ID echoed back +------------+ Client Server]]></artwork></figure>]]></artwork> </figure> <t> An example of a suitable request is a GET request in a Confirmable message that includes only an If-None-Match option and a token of the greatest length that the client intends to use. Any response with the same token echoed back indicates that tokens up to that length are supported by the server. </t> <t> Since network addresses may change, a clientSHOULD NOT<bcp14>SHOULD NOT</bcp14> assume that extended token lengths are supported by a server for an unlimited duration. Unless additional information is available, the client should assume that addresses (and therefore extended token lengths) are valid for a minimum of 1800s,s andfora maximum of 86400 s (1 day). A client may use additional forms of input into this determination. Forinstanceinstance, a client may assume a serverwhichthat is in the same subnet as the client has a similar address lifetime as the client. The client may use DHCP lease times or Router Advertisements to set the limits. For servers that are not local, if the server was looked up using DNS, then the DNS resource record will have a Time ToLive,Live (TTL), and the extended token length should be kept for only that amount of time. </t> <t> If a server supports extended token lengths but receives a request with a token of a length it is unwilling or unable to handle, itMUST NOT<bcp14>MUST NOT</bcp14> reject the message, as that would imply that extended token lengths are not supported at all. Instead, if the server cannot handle the request at the time, itSHOULD<bcp14>SHOULD</bcp14> return a 5.03 (Service Unavailable) response; if the server will never be able to handle the request (e.g., because the token is too large), itSHOULD<bcp14>SHOULD</bcp14> return a 4.00 (Bad Request) response. </t><t> <list style="hanging"> <t hangText="Design Note:"><aside> <t>Design Note: The requirement to return an error response when a token cannot be handled might seem somewhat contradictory, as returning the error response requires the server also to return the token it cannot handle. However, processing a request usually involves a number of steps from receiving the message to passing it to application logic. The idea is that a server implementing this extension supports large tokens at least in its first few processing steps, enough to return an error response rather than a Reset message. </t></list> </t> <t> <list style="hanging"> <t hangText="Design Note:"></aside> <aside> <t>Design Note: Tomakeprevent the trial-and-error-based discoverynotfrom becoming too complicated, no effort is made to indicate the maximum supported token length. A client implementation would probably already choose the shortest token possible for the task(like(such as beingstatelessstateless, as described in <xreftarget="stateless-clients"/>),target="stateless-clients" format="default"/>), so it would probably not be able to reduce the length any further anyway should a server indicate a lower limit. </t></list> </t></aside> </section> </section> <sectiontitle="Intermediaries" anchor="hop-by-hop">anchor="hop-by-hop" numbered="true" toc="default"> <name>Intermediaries</name> <t> Tokens are a hop-by-hop feature:Ifif there are one or more intermediaries between a client and a server, every token is scoped to the exchange between a node in the client role and the node in the server role that it is immediately interacting with. </t> <t> When an intermediary receives a request, the only requirement is that it echoes the token back in any resulting response. There is no requirement or expectation that an intermediary passes a client's token on to a server or that an intermediary uses extended token lengths itself in its request to satisfy a request with an extended token length. Discovery needs to be performed for each hop where extended token lengths are to be used. </t> </section> </section><!-- **************************************************************** --> <!-- **************************************************************** --> <!-- **************************************************************** --> <!-- **************************************************************** --><sectiontitle="Stateless Clients" anchor="stateless-clients">anchor="stateless-clients" numbered="true" toc="default"> <name>Stateless Clients</name> <t> A client can be alleviated of keeping per-request state as follows:<list style="numbers"> <t></t> <ol spacing="normal" type="1"><li> The client serializes (parts of) its per-request state into a sequence of bytes and sends those bytes as the token of its request to the server.</t> <t></li> <li> The server returns the token verbatim in the response to the client, which allows the client to recover the state and process the response as if it had kept the state locally.</t> </list> </t></li> </ol> <t> As servers are just expected to return any token verbatim to the client, this implementation strategy for clients does not impact the interoperability of client and server implementations. However, there are a number of significant,non-obviousnonobvious implications (e.g., related to security and other CoAP protocol features) that client implementations need take into consideration. </t> <t> The following subsections discuss some of these considerations. </t> <sectiontitle="Serializinganchor="serialized-state" numbered="true" toc="default"> <name>Serializing ClientState" anchor="serialized-state">State</name> <t> The format of the serialized state is generally an implementation detail of the client and opaque to the server. However, serialized state information is an attractive target for both unwanted nodes (e.g., on-path attackers) and wanted nodes (e.g., any configured forward proxy) on the path. The serialization format therefore needs to include security measures such as the following:<list style="symbols"> <t></t> <ul spacing="normal"> <li> A clientSHOULD<bcp14>SHOULD</bcp14> protect the integrity of the state information serialized in a token.</t> <t></li> <li> Even when the integrity of the serialized state is protected, an attacker may still replay a response, making the client believe it sent the same request twice. For this reason, the clientSHOULD<bcp14>SHOULD</bcp14> implement replay protection (e.g., by using sequence numbers and a replay window). For replay protection, integrity protection isREQUIRED. </t> <t><bcp14>REQUIRED</bcp14>. </li> <li> If processing a response without keeping request state is sensitive to the time elapsed since sending the request, then the clientSHOULD<bcp14>SHOULD</bcp14> include freshness information (e.g., a timestamp) in the serialized state and reject any response where the freshness information is insufficiently fresh.</t> <t></li> <li> Information in the serialized state may be privacy sensitive. A clientSHOULD<bcp14>SHOULD</bcp14> encrypt the serialized state if it containsprivacy sensitiveprivacy-sensitive information that an attacker would not get otherwise.</t> <t></li> <li> When a client changes the format of the serialized state, itSHOULD<bcp14>SHOULD</bcp14> prevent false interoperability with the previous format (e.g., by changing the key used for integrity protection or changing a field in the serialized state).</t> </list> </t></li> </ul> </section> <sectiontitle="Usingnumbered="true" toc="default"> <name>Using ExtendedTokens">Tokens</name> <t> A client that depends on support for extended token lengths (<xreftarget="extended-tokens"/>)target="extended-tokens" format="default"/>) from the server to avoid keeping request state needs to perform a discovery of support (<xreftarget="discovery"/>)target="discovery" format="default"/>) before it can be stateless. </t> <t> This discoveryMUST<bcp14>MUST</bcp14> be performed in a stateful way, i.e., keeping state for the request (<xreftarget="stateful-discovery"/>):target="stateful-discovery" format="default"/>). If the client was stateless from thestartstart, and the server does not support extended tokens, thenanyno error message couldnotbeprocessedprocessed, since the state would neither be present at the client nor returned in the Reset message (<xreftarget="stateless-discovery"/>).target="stateless-discovery" format="default"/>). </t> <figureanchor="stateful-discovery" title="Dependinganchor="stateful-discovery"> <name>Depending on Extended Tokens for Being Stateless First Requires a Successful Stateful Discovery ofSupport"><artwork align="center"><![CDATA[Support</name> <artwork align="center" name="" type="" alt=""><![CDATA[ +-----------------+ dummy request +------------+ | | | with extended | | | | | token | | | .-<-+->------|=====================>|------. | | _|_ | | | | | / \ stored | | | | | \___/ state | | | | | | | | | | | '->-+-<------|<=====================|------' | | | | response with | | | | | extended token | | | | | echoed back | | | | | | | | | | | | | | | request with | | | | | serialized state | | | | | as token | | | +--------|=====================>|------. | | | | | | | look ma, | | | | | no state! | | | | | | | | | | +--------|<=====================|------' | | | | response with | | | v | token echoed back | | +-----------------+ +------------+ Client Server]]></artwork></figure>]]></artwork> </figure> <figureanchor="stateless-discovery" title="Statelessanchor="stateless-discovery"> <name>Stateless Discovery of Support Does NotWork"><artwork align="center"><![CDATA[Work</name> <artwork align="center" name="" type="" alt=""><![CDATA[ +-----------------+ dummy request +------------+ | | | with extended | | | | | token | | | +--------|=====================>|------. | | | | | | | | | | | | | | | | | | | | | | ???|<---------------------|------' | | |resetReset message | | | | with only message | | +-----------------+ ID echoed back +------------+ Client Server]]></artwork></figure>]]></artwork> </figure> <t> In environments where support can be reliably discovered through some other means, the discovery of support isOPTIONAL.<bcp14>OPTIONAL</bcp14>. An example for this is the <xreftarget="I-D.ietf-6tisch-minimal-security">Constrainedtarget="I-D.ietf-6tisch-minimal-security" format="default">Constrained Join Protocol (CoJP) in a 6TiSCH network</xref>, where support for extended tokens is required from all relevant parties. </t> </section> <sectiontitle="Transmitting Messages">numbered="true" toc="default"> <name>Transmitting Messages</name> <t> In <xreftarget="RFC7252">CoAPtarget="RFC7252" format="default">CoAP over UDP</xref>, a client has the choice between Confirmable and Non-confirmable messages for requests. When using Non-confirmable messages, a client does not have to keep anymessage exchangemessage-exchange state, which can help in the goal of avoiding state. When using Confirmable messages, a client needs to keepmessage exchangemessage-exchange state for performing retransmissions and handling Acknowledgement and Reset messages, however. Non-confirmable messages are therefore better suited for avoiding state. In any case, a client still needs to keepcongestion controlcongestion-control state, i.e., maintain state for each node it communicates with and enforce limits like NSTART. </t> <t> As perSection 5.2 of RFC 7252,<xref target="RFC7252" sectionFormat="of" section="5.2" />, a client must be prepared to receive a response as a piggybacked response, a separate response, or a Non-confirmable response, regardless of the message type used for the request. A stateless clientMUST<bcp14>MUST</bcp14> handle these response types as follows:<list style="symbols"> <t></t> <ul spacing="normal"> <li> If a piggybacked response passes the checks for token integrity and freshness (<xreftarget="serialized-state"/>),target="serialized-state" format="default"/>), the client processes the message as specified in RFC 7252; otherwise, it processes the acknowledgement portion of the message as specified in RFC 7252 and silently discards the response portion.</t> <t></li> <li> If a separate response passes the checks for token integrity and freshness, the client processes the message as specified in RFC 7252; otherwise, it rejects the message as specified inSection 4.2 of RFC 7252. </t> <t><xref target="RFC7252" sectionFormat="of" section="4.2" />. </li> <li> If a Non-confirmable response passes the checks for token integrity and freshness, the client processes the message as specified in RFC 7252; otherwise, it rejects the message as specified inSection 4.3 of RFC 7252. </t> </list> </t><xref target="RFC7252" sectionFormat="of" section="4.3" />. </li> </ul> </section> </section> <sectiontitle="Stateless Intermediaries" anchor="stateless-intermediaries">anchor="stateless-intermediaries" numbered="true" toc="default"> <name>Stateless Intermediaries</name> <t> Tokens are a hop-by-hopfeature:feature. If a client makes a request to an intermediary, that intermediary needs to store the client's token (along with the client's transport address) while it makes its own request towards the origin server and waits for the response. When the intermediary receives the response, it looks up the client's token and transport address for the received request and sends an appropriate response to the client. </t> <t> An intermediary might want to be "stateless" not only in its role as a client but also in its role as a server, i.e., be alleviated of storing the client information for the requests it receives. </t> <t> Such an intermediary can be implemented by serializing the client information along with the request state into the token towards the origin server. When the intermediary receives the response, it can recover the client information from the token and use it to satisfy the client'srequest and thereforerequest; therefore, the intermediary doesn't need to storeitthe information itself. </t> <t> The following subsections discuss some considerations for this approach. </t> <sectiontitle="Observing Resources">numbered="true" toc="default"> <name>Observing Resources</name> <t> One drawback of the approach is that an intermediary, without keeping request state, is unable to aggregate multiple requests for the same target resource, which can significantly reduce efficiency. In particular, when clients observe <xreftarget="RFC7641">observe</xref>target="RFC7641" format="default"></xref> the same resource, aggregating requests isREQUIRED (Section 3.1 of RFC 7641).<bcp14>REQUIRED</bcp14> (<xref target="RFC7641" sectionFormat="of" section="3.1" />). This requirement cannot be satisfied without keeping request state. </t> <t> Furthermore, an intermediary that does not keep track of the clients observing a resource is not able to determine whether these clients are still interested in receiving further notifications(Section 3.5 of RFC 7641)(<xref target="RFC7641" sectionFormat="of" section="3.5" />) or want to cancel an observation(Section 3.6 of RFC 7641).(<xref target="RFC7641" sectionFormat="of" section="3.6" />). </t> <t> Therefore, an intermediaryMUST NOT<bcp14>MUST NOT</bcp14> include an Observe Option in requests it sends without keeping both the request state for the requests it sends and the client information for the requests it receives. </t> </section> <sectiontitle="Block-Wise Transfers">numbered="true" toc="default"> <name>Block-Wise Transfers</name> <t> When using <xreftarget="RFC7959">block-wisetarget="RFC7959" format="default">block-wise transfers</xref>, a server might not be able to distinguish blocks originating from different clients once they have been forwarded by an intermediary. Intermediaries need to ensure that this does not lead to inconsistent resource state by keeping distinct block-wise request operations on the same resource apart, e.g., utilizing the <xreftarget="I-D.ietf-core-echo-request-tag">Request-Tagtarget="I-D.ietf-core-echo-request-tag" format="default">Request-Tag Option</xref>. </t> </section> <sectiontitle="Gateway Timeouts">numbered="true" toc="default"> <name>Gateway Timeouts</name> <t> As perSection 5.7.1 of RFC 7252,<xref target="RFC7252" sectionFormat="of" section="5.7.1" />, an intermediary isREQUIRED<bcp14>REQUIRED</bcp14> to return a 5.04 (Gateway Timeout) response if it cannot obtain a response within a timeout. However, if an intermediary does not keep the client information for the requests it receives, it cannot return such a response. Therefore, in this case, the gateway cannot return such a response and as such cannot implement such a timeout. </t> </section> <sectiontitle="Extended Tokens">numbered="true" toc="default"> <name>Extended Tokens</name> <t> A client may make use of extended token lengths in a request to an intermediary that wants to be "stateless". This means that such an intermediary may have to serialize potentially very large client information into its token towards the origin server. The tokens can grow even further when it progresses along a chain of intermediaries that all want to be "stateless". </t> <t> IntermediariesSHOULD<bcp14>SHOULD</bcp14> limit the size of client information they are serializing into their own tokens. An intermediary can do this, for example, by limiting the extended token lengths it accepts from its clients (see <xreftarget="discovery"/>)target="discovery" format="default"/>) or by keeping the client information locally when the client information exceeds the limit (i.e., not being "stateless"). </t> </section> </section><!-- **************************************************************** --> <!-- **************************************************************** --> <!-- **************************************************************** --> <!-- **************************************************************** --><sectiontitle="Security Considerations" anchor="security">anchor="security" numbered="true" toc="default"> <name>Security Considerations</name> <sectiontitle="Extended Tokens">numbered="true" toc="default"> <name>Extended Tokens</name> <t> Tokens significantly larger than the 8 bytes specified in RFC 7252 have implications -- inparticularparticular, for nodes with constrained memory size -- that need to be mitigated. A node in the server role supporting extended token lengths may be vulnerable to adenial-of-servicedenial of service when an attacker (either on-path or a malicious client) sends large tokens to fill up the memory of the node. Implementations need to be prepared to handle such messages. </t> </section> <sectiontitle="Statelessnumbered="true" toc="default"> <name>Stateless Clients andIntermediaries">Intermediaries</name> <t> Transporting the state needed by a client to process a response as serialized state information in the token has several significant andnon-obviousnonobvious security and privacy implications that need to be mitigated; see <xreftarget="serialized-state"/>target="serialized-state" format="default"/> for recommendations. </t> <t> In addition to the format requirements outlined there, implementations need to ensure that they are not vulnerable to maliciously crafted, delayed, or replayed tokens. </t> <t> It is generally expected that the use of encryption, integrity protection, and replay protection for serialized state is appropriate. </t> <t> In the absence of integrity and replay protection, an on-path attacker or rogue server/intermediary could return a state (either one modified in a reply, or an unsolicited one) that could alter the internal state of the client. </t> <t> It is for this reason that at least the use of integrity protection on the token is always recommended. </t> <t> Itmaybemay be that in some very specificcase,cases, as a result of a careful and detailed analysis of any potential attacks, it is decided thatthere may be cases wheresuch cryptographic protections do not add value. The authors of this document have not found such a use case as yet, but this is a local decision. </t> <t> It should further be emphasized that the encrypted state is created by the sendingnode,node and decrypted by the same node when receiving a response. The key is not shared with any other system.ThereforeTherefore, the choice of encryption scheme and the generation of the key for this system is purely a local matter. </t> <t> When encryption is used, the use of <xreftarget="RFC3610">AES-CCM</xref>target="RFC3610" format="default">AES-CCM</xref> with a 64-bit tag is recommended, combined with a sequence number and a replay window. This choice is informed by available hardware acceleration of on many constrained systems. If a different algorithm is available accelerated on the sender, with similar or stronger strength, then itSHOULD<bcp14>SHOULD</bcp14> be preferred. Where privacy of the state is not required, and encryption is not needed, <xreftarget="RFC6234">HMAC-SHA-256</xref>,target="RFC6234" format="default">HMAC-SHA-256</xref>, combined with a sequence number and a replay window, may be used. </t> <t> This size of the replay window depends upon the number of requests that need to be outstanding. This can be determined from the rate at which new ones aremade,made and the expectedduration intime period during which responses are expected. </t> <t> For instance, given a CoAP MAX_TRANSMIT_WAIT of 93 s(Section 4.8.2 of <xref target="RFC7252"/>,(<xref target="RFC7252" sectionFormat="of" section="4.8.2"/>), any request that is not answered within 93 s will be considered to have failed. At a request rate of one request per 10 s, at most 10 (ceil(9.3)) requests can be outstanding at a time, and any convenient replay window larger than 20 will work. As replay windows are often implemented with a sliding window and a bit, the use of a 32-bit window would be sufficient. </t> <t> For use cases where requests are being relayed from another node, the request rate may be estimated by the total link capacity allocated for that kind of traffic. An alternate view would consider how many IPv6 Neighbor Cache Entries (NCEs) the system can afford to allocate for this use. </t> <t> When using an encryption mode that depends on a nonce, such as AES-CCM, repeated use of the same nonce under the same key causes the cipher to fail catastrophically. </t> <t> If a nonce is ever used for more than one encryption operation with the same key, then the same key stream gets used to encrypt bothplaintextsplaintexts, and the confidentiality guarantees are voided. Devices with low-quality entropy sources -- as is typical with constrained devices, which incidentally happen to be a natural candidate for the stateless mechanism described in this document -- need to carefully pick anonce generationnonce-generation mechanism that provides the above uniqueness guarantee. </t> <t> <xreftarget="RFC8613" /> appendixtarget="RFC8613"/>, Appendix B.1.1 ("Sender Sequence Number") provides a model for how to maintainnon-repeatingnonrepeating nonces without causing excessive wear of flash memory. </t> </section> </section><!-- **************************************************************** --> <!-- **************************************************************** --> <!-- **************************************************************** --> <!-- **************************************************************** --><sectiontitle="IANA Considerations">numbered="true" toc="default"> <name>IANA Considerations</name> <sectiontitle="CoAPnumbered="true" toc="default"> <name>CoAP Signaling OptionNumber">Number</name> <t> The followingentries areentry has been added to the "CoAP Signaling Option Numbers" registry within the "CoRE Parameters" registry. </t><texttable> <ttcol<table align="center"> <name>CoAP Signalling Option Number</name> <thead> <tr> <th align="left">Appliesto</ttcol> <ttcol align="right">Number</ttcol> <ttcol align="left">Name</ttcol> <ttcol align="left">Reference</ttcol> <c>7.01</c> <c>TBD</c> <c>Extended-Token-Length</c> <c>[[this document]]</c> </texttable>to</th> <th align="right">Number</th> <th align="left">Name</th> <th align="left">Reference</th> </tr> </thead> <tbody> <tr> <td align="left">7.01</td> <td align="right">6</td> <td align="left">Extended-Token-Length</td> <td align="left">RFC 8974</td> </tr> </tbody> </table> <t>[[NOTE TO RFC EDITOR: Please replace "TBD" in this section and in <xref target="capability-option-definition"/> with the code point assigned by IANA.]]</t> </section> </section><!-- **************************************************************** --> <!-- **************************************************************** --> <!-- **************************************************************** --> <!-- **************************************************************** --></middle> <back><!-- **************************************************************** --> <!-- **************************************************************** --> <!-- ****************************************************************<displayreference target="I-D.ietf-core-echo-request-tag" to="ECHO-REQUEST-TAG"/> <displayreference target="I-D.ietf-6tisch-minimal-security" to="6TISCH-MIN-SEC"/> <references> <name>References</name> <references> <name>Normative References</name> <xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.2119.xml"/> <xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.7252.xml"/> <xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.7641.xml"/> <xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.7959.xml"/> <xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.8174.xml"/> <xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.8323.xml"/> </references> <references> <name>Informative References</name> <xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.3610.xml"/> <xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.6234.xml"/> <xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.7228.xml"/> <xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.8613.xml"/> <!-- [I-D.ietf-core-echo-request-tag] IESG state - Waiting for AD Go-Ahead::AD Followup --> <xi:include href="https://datatracker.ietf.org/doc/bibxml3/reference.I-D.ietf-core-echo-request-tag.xml"/> <!--****************************************************************[I-D.ietf-6tisch-minimal-security] in MISSREF state as of 12/5/20 --><references title="Normative References"> &RFC2119; &RFC7252; &RFC7641; &RFC7959; &RFC8174; &RFC8323;<xi:include href="https://datatracker.ietf.org/doc/bibxml3/reference.I-D.ietf-6tisch-minimal-security.xml"/> </references><references title="Informative References"> &RFC3610; &RFC6234; &RFC7228; <?rfc include="reference.RFC.8613" ?> &I-D.ietf-core-echo-request-tag; &I-D.ietf-6tisch-minimal-security;</references><!-- **************************************************************** --> <!-- **************************************************************** --> <!-- **************************************************************** --> <!-- **************************************************************** --><sectiontitle="Updatedanchor="message-formats" numbered="true" toc="default"> <name>Updated MessageFormats" anchor="message-formats">Formats</name> <t> In <xreftarget="extended-tokens"/>,target="extended-tokens" format="default"/>, this document updates the CoAP message formats by specifying a new definition of theTKL"TKL" field in the message header. As an alternative presentation of this update, this appendix shows the CoAP message formats for <xreftarget="RFC7252">CoAPtarget="RFC7252" format="default">CoAP over UDP</xref> and <xreftarget="RFC8323">CoAPtarget="RFC8323" format="default">CoAP over TCP, TLS, and WebSockets</xref> with the new definition applied. </t> <sectiontitle="CoAPnumbered="true" toc="default"> <name>CoAP overUDP"> <figure><artwork align="center"><![CDATA[UDP</name> <artwork align="center" name="" type="" alt=""><![CDATA[ 0 1 2 3 4 5 6 7 +-------+-------+---------------+ | | | | | Ver | T | TKL | 1 byte | | | | +-------+-------+---------------+ | | | Code | 1 byte | | +-------------------------------+ | | | | | | +- Message ID -+ 2 bytes | | | | | | +-------------------------------+ \ \ / TKL / 0-2 bytes \ (extended) \ +-------------------------------+ \ \ / Token / 0-65804 bytes \ \ +-------------------------------+ \ \ / / \ \ / Options / 0 or more bytes \ \ / / \ \ +---------------+---------------+ | | | | 15 | 15 | 1 byte (if payload) | | | +---------------+---------------+ \ \ / / \ \ / Payload / 0 or more bytes \ \ / / \ \ +-------------------------------+]]></artwork></figure>]]></artwork> </section> <sectiontitle="CoAPnumbered="true" toc="default"> <name>CoAP overTCP/TLS"> <figure><artwork align="center"><![CDATA[TCP/TLS</name> <artwork align="center" name="" type="" alt=""><![CDATA[ 0 1 2 3 4 5 6 7 +---------------+---------------+ | | | | Len | TKL | 1 byte | | | +---------------+---------------+ \ \ / Len / 0-4 bytes \ (extended) \ +-------------------------------+ | | | Code | 1 byte | | +-------------------------------+ \ \ / TKL / 0-2 bytes \ (extended) \ +-------------------------------+ \ \ / Token / 0-65804 bytes \ \ +-------------------------------+ \ \ / / \ \ / Options / 0 or more bytes \ \ / / \ \ +---------------+---------------+ | | | | 15 | 15 | 1 byte (if payload) | | | +---------------+---------------+ \ \ / / \ \ / Payload / 0 or more bytes \ \ / / \ \ +-------------------------------+]]></artwork></figure>]]></artwork> </section> <sectiontitle="CoAPnumbered="true" toc="default"> <name>CoAP overWebSockets"> <figure><artwork align="center"><![CDATA[WebSockets</name> <artwork align="center" name="" type="" alt=""><![CDATA[ 0 1 2 3 4 5 6 7 +---------------+---------------+ | | | | 0 | TKL | 1 byte | | | +---------------+---------------+ | | | Code | 1 byte | | +-------------------------------+ \ \ / TKL / 0-2 bytes \ (extended) \ +-------------------------------+ \ \ / Token / 0-65804 bytes \ \ +-------------------------------+ \ \ / / \ \ / Options / 0 or more bytes \ \ / / \ \ +---------------+---------------+ | | | | 15 | 15 | 1 byte (if payload) | | | +---------------+---------------+ \ \ / / \ \ / Payload / 0 or more bytes \ \ / / \ \ +-------------------------------+]]></artwork></figure>]]></artwork> </section> </section><!-- **************************************************************** --> <!-- **************************************************************** --> <!-- **************************************************************** --> <!-- **************************************************************** --><sectiontitle="Acknowledgements" numbered="no">numbered="false" toc="default"> <name>Acknowledgements</name> <t> This document is based on the requirementsofof, and workon the <xref target="I-D.ietf-6tisch-minimal-security">Minimal Security Frameworkon, "Constrained Join Protocol (CoJP) for6TiSCH</xref>6TiSCH" (January 2020) byMalisa Vucinic, Jonathan Simon, Kris Pister,<contact fullname="Mališa Vučinić"/>, <contact fullname="Jonathan Simon"/>, <contact fullname="Kris Pister"/>, andMichael Richardson.<contact fullname="Michael Richardson"/>. </t><!-- sorted by last name --><t> Thanks toChristian Amsuss, Carsten Bormann, Roman Danyliw, Christer Holmberg, Benjamin Kaduk, Ari Keranen, Erik Kline, Murray Kucherawy, Warren Kumari, Barry Leiba, David Mandelberg, Dan Romascanu, Jim Schaad, Goran Selander, Malisa Vucinic, Eric Vyncke, and Robert Wilton<contact fullname="Christian Amsüss"/>, <contact fullname="Carsten Bormann"/>, <contact fullname="Roman Danyliw"/>, <contact fullname="Christer Holmberg"/>, <contact fullname="Benjamin Kaduk"/>, <contact fullname="Ari Keränen"/>, <contact fullname="Erik Kline"/>, <contact fullname="Murray Kucherawy"/>, <contact fullname="Warren Kumari"/>, <contact fullname="Barry Leiba"/>, <contact fullname="David Mandelberg"/>, <contact fullname="Dan Romascanu"/>, <contact fullname="Jim Schaad"/>, <contact fullname="Göran Selander"/>, <contact fullname="Mališa Vučinić"/>, <contact fullname="Éric Vyncke"/>, and <contact fullname="Robert Wilton"/> for helpful comments and discussions that have shaped the document. </t> <t> Special thanks toJohn Mattsson<contact fullname="John Mattsson"/> for his contributions to the security considerations of the document, and toThomas Fossati<contact fullname="Thomas Fossati"/> for his in-depth review, copious comments, and suggested text. </t> </section><!-- **************************************************************** --> <!-- **************************************************************** --> <!-- **************************************************************** --> <!-- **************************************************************** --></back> </rfc>