A CoAP endpoint (or proxy) MUST support either both or neither of the Q-Block1 and Q-Block2 Options.  To indicate support for Q-Block2 responses, the CoAP client MUST include the Q-Block2 Option in a GET or similar request, the Q-Block2 Option in a PUT or similar request, or the Q-Block1 Option in a PUT (if supported) to send back a message body that is too large to fit into a single IP packet RFC7959. <del> If Q-Block1 Option is present in a request or Q-Block2 Option in a response (i.e., in that message to the payload of which it pertains), it indicates a block-wise transfer and describes how this specific block-wise payload forms part of the entire body being transferred. If it is present in the opposite direction, it provides additional control on how that payload will be formed or was processed. </del> Implementation of the Q-Block1 and Q-Block2 Options is intended to be optional.  However, when it is present in a CoAP message, it MUST be processed (or the message rejected).  Therefore, Q-Block1 and Q-Block2 Options are identified as Critical options.  The Q-Block1 and Q-Block2 Options are unsafe to forward.  That is, a CoAP proxy that does not understand the Q-Block1 (or Q-Block2) Option MUST reject the request or response that uses either option. 2.01 (Created) This Response Code indicates successful receipt of the entire body <del> and the resource was created. </del>  2.04 (Changed) This Response Code indicates successful receipt of the entire body <del> and the resource was updated. </del>  2.31 (Continue) This Response Code can be used to indicate that all of the blocks up to and including the Q-Block1 Option block NUM (all having the <del> M bit set) in the response have been successfully received. </del>  A response using this Response Code SHOULD NOT be generated for every received Q-Block1 Option request.  It SHOULD only be matching client request which contains the Request-Tag that is being used for this Q-Block1 body.  4.13 (Request Entity Too Large) This Response Code can be returned under similar conditions to these missing blocks is as follows: The token to use for the response SHOULD be the token that was used <del> in the highest block number received so far with the same Request-Tag </del>  value.  Note that the use of any received token with the same <del> Request-Tag would work, but providing the one used in the highest </del>  received block number will aid any troubleshooting.  The client will use the token to determine what is the previously sent request to obtain the Request-Tag value to be used. payloads. For the server receiving NON Q-Block1 requests, it SHOULD send back a <del> 2.31 (Continue) or 4.08 (Request Entity Incomplete) Response Code on receipt of the last of the MAX_PAYLOADS payloads to prevent the client unnecessarily delaying.  If the last of the MAX_PAYLOADS payloads does not arrive (or the final payload where the M bit is not set does not arrive), then the server SHOULD delay for NON_RECEIVE_TIMEOUT before sending the 4.08 (Request Entity Incomplete) Response Code. </del>  It is possible that the client may start transmitting the next set of MAX_PAYLOADS payloads before the server times out on waiting for the last of the previous MAX_PAYLOADS payloads.  On receipt of the first <del> payload from the new set of MAX_PAYLOADS payloads, the server SHOULD send a 4.08 (Request Entity Incomplete) Response Code indicating any missing payloads from any previous MAX_PAYLOADS payloads.  Upon receipt of the 4.08 (Request Entity Incomplete) Response Code, the client SHOULD send the missing payloads before continuing to send the remainder of the MAX_PAYLOADS payloads and then go into another NON_TIMEOUT delay prior to sending the next set of payloads. </del>  For the client receiving NON Q-Block2 responses, it SHOULD send a <del> request for the next set of payloads or a request for the missing payloads upon receipt of the last of the MAX_PAYLOADS payloads to prevent the server unnecessarily delaying the transmission of the body.  If the last of the MAX_PAYLOADS payloads does not arrive (or the final payload where the M bit is not set does not arrive), then the client SHOULD delay for NON_RECEIVE_TIMEOUT before sending the request for the missing payloads. </del>  The request that the client sends to acknowledge the receipt of all the current set of MAX_PAYLOADS payloads is the 'Continue' Q-Block2 Observe Option, if appropriate for an unsolicited response) rather than as a request for the remaining missing blocks.  The client does not need to acknowledge the receipt of the entire body. client, but some blocks are dropped in transmission as illustrated in B3non1. <del> The server realizes that some blocks are missing and asks for the missing ones in one go (B3non2).  It does so by indicating which blocks have been received in the data portion of the response.  The token used in the response should be the token that was used in the highest block number received payload.  The client can then derive the Request-Tag by matching the token with the sent request. </del>  Under high levels of traffic loss, the client can elect not to retry sending missing blocks of data by "forgetting" all the tracked tokens

find another name than Quick-Block
A poll is ongoing. Updated to Q-Block in -02, but open to change if we get more inputs

A CoAP endpoint (or proxy) MUST support either both or neither of the Q-Block1 and Q-Block2 Options. <ins> If Q-Block1 Option is present in a request or Q-Block2 Option in a response (i.e., in that message to the payload of which it pertains), it indicates a block-wise transfer and describes how this specific block-wise payload forms part of the entire body being transferred. If it is present in the opposite direction, it provides additional control on how that payload will be formed or was processed. </ins> To indicate support for Q-Block2 responses, the CoAP client MUST include the Q-Block2 Option in a GET or similar request, the Q-Block2 Option in a PUT or similar request, or the Q-Block1 Option in a PUT (if supported) to send back a message body that is too large to fit into a single IP packet RFC7959.  Implementation of the Q-Block1 and Q-Block2 Options is intended to be optional.  However, when it is present in a CoAP message, it MUST be processed (or the message rejected).  Therefore, Q-Block1 and Q-Block2 Options are identified as Critical options. <ins> With CoAP over UDP, the way a request message is rejected for Critical options depends on the message type.  A Confirmable message with a unknown Critical option is rejected with a 4.02 (Bad Option) response (Section 5.4.1 of RFC7252).  A Non-confirmable message with a unknown Critical option is either rejected with a Reset message or just silently ignored (Section 5.4.1 and 4.3 of RFC7252).  To reliably get a rejection message, it is therefore REQUIRED that clients use a Confirmable message for determining support for Q-Block1 and Q-Block2 options. </ins> The Q-Block1 and Q-Block2 Options are unsafe to forward.  That is, a CoAP proxy that does not understand the Q-Block1 (or Q-Block2) Option MUST reject the request or response that uses either option. 2.01 (Created) This Response Code indicates successful receipt of the entire body  <ins> and the resource was created.  The token used SHOULD be from the last received payload.  The client should then release all of the tokens used for this body. </ins> 2.04 (Changed) This Response Code indicates successful receipt of the entire body  <ins> and the resource was updated.  The token used SHOULD be from the last received payload.  The client should then release all of the tokens used for this body. </ins> 2.31 (Continue) This Response Code can be used to indicate that all of the blocks up to and including the Q-Block1 Option block NUM (all having the  <ins> M bit set) in the response have been successfully received.  The token used SHOULD be from the last received payload. </ins> A response using this Response Code SHOULD NOT be generated for every received Q-Block1 Option request.  It SHOULD only be matching client request which contains the Request-Tag that is being used for this Q-Block1 body. <ins> The token used in the response SHOULD be from the last received payload.  See code for further information. </ins> 4.13 (Request Entity Too Large) This Response Code can be returned under similar conditions to these missing blocks is as follows: The token to use for the response SHOULD be the token that was used  <ins> in the last block number received so far with the same Request-Tag </ins> value.  Note that the use of any received token with the same  <ins> Request-Tag would work, but providing the one used in the last </ins> received block number will aid any troubleshooting.  The client will use the token to determine what is the previously sent request to obtain the Request-Tag value to be used. payloads. For the server receiving NON Q-Block1 requests, it SHOULD send back a  <ins> 2.31 (Continue) Response Code on receipt of all of the MAX_PAYLOADS payloads to prevent the client unnecessarily delaying.  Otherwise the server SHOULD delay for NON_RECEIVE_TIMEOUT, before sending the 4.08 (Request Entity Incomplete) Response Code.  The NON_RECEIVE_TIMEOUT delay can be reduced if either the last of the MAX_PAYLOADS payloads or the final payload with the M bit unset arrives, but SHOULD NOT be reduced to zero as packets may arrive in the wrong order. </ins> It is possible that the client may start transmitting the next set of MAX_PAYLOADS payloads before the server times out on waiting for the last of the previous MAX_PAYLOADS payloads.  On receipt of the first  <ins> received payload from the new set of MAX_PAYLOADS payloads, the server SHOULD send a 4.08 (Request Entity Incomplete) Response Code indicating any missing payloads from any previous MAX_PAYLOADS payloads.  Upon receipt of the 4.08 (Request Entity Incomplete) Response Code, the client SHOULD send the missing payloads before continuing to send the remainder of the MAX_PAYLOADS payloads and then go into another NON_TIMEOUT delay prior to sending the next set of payloads. </ins> For the client receiving NON Q-Block2 responses, it SHOULD send a  <ins> request for the next set of payloads on receipt of all of the MAX_PAYLOADS payloads to prevent the server unnecessarily delaying. Otherwise the client SHOULD delay for NON_RECEIVE_TIMEOUT, before sending the request for the missing payloads.  The NON_RECEIVE_TIMEOUT delay can be reduced if either the last of the MAX_PAYLOADS payloads or the final payload with the M bit unset arrives, but SHOULD NOT be reduced to zero as packets may arrive in the wrong order. </ins> The request that the client sends to acknowledge the receipt of all the current set of MAX_PAYLOADS payloads is the 'Continue' Q-Block2 Observe Option, if appropriate for an unsolicited response) rather than as a request for the remaining missing blocks. <ins> It is possible that the server may start transmitting the next set of MAX_PAYLOADS payloads before the client times out on waiting for the last of the previous MAX_PAYLOADS payloads.  On receipt of the first received payload from the new set of MAX_PAYLOADS payloads, the client SHOULD send a request for the missing payloads indicating any missing payloads from any previous MAX_PAYLOADS payloads.  Upon receipt of the request for missing payloads, the server SHOULD send the missing payloads before continuing to send the remainder of the MAX_PAYLOADS payloads and then go into another NON_TIMEOUT delay prior to sending the next set of payloads. </ins> The client does not need to acknowledge the receipt of the entire body. client, but some blocks are dropped in transmission as illustrated in B3non1.  <ins> On seeing a payload from the next set of payloads, the server realizes that some blocks are missing from the previous MAX_PAYLOADS payloads and asks for the missing blocks in one go (B3non2).  It does so by indicating which blocks have been received in the data portion of the response.  The token used in the response should be the token that was used in the last block number received payload.  The client can then derive the Request-Tag by matching the token with the sent request. </ins> Under high levels of traffic loss, the client can elect not to retry sending missing blocks of data by "forgetting" all the tracked tokens


Note that the same performance benefits can be applied to Confirmable messages if the value of NSTART is increased from 1 (Section 4.7 of <del> RFC7252).  However, the asymmetrical packet loss is not a benefit here.  Some sample examples with Confirmable messages are provided in CON. </del>  There is little, if any, benefit of using these options with CoAP running over a reliable connection RFC8323.  In this case, there is 1.2. <del> This document updates the 4.08 (Request Entity Incomplete) by defining an additional message format for reporting on payloads using the Q-Block1 Option that are not received by the server. </del>  See code for more details. The formatting of this table follows the one used in Table 4 of RFC7252 (Section 5.10).  The C, U, N, and R columns indicate the properties Critical, Unsafe, NoCacheKey, and Repeatable defined in <del> Section 5.4 of RFC7252.  Only C and U columns are marked for the Q-Block1 Option.  C, U, and R columns are marked for the Q-Block2 Option. </del>  The Q-Block1 and Q-Block2 Options can be present in both the request and response messages.  The Q-Block1 Option pertains to the request The Content-Format Option applies to the body, not to the payload (i.e., it must be the same for all payloads of the same body). <del> Q-Block1 Option is useful with the payload-bearing POST, PUT, PATCH, and iPATCH requests and their responses (2.01 and 2.04). </del>  Q-Block2 Option is useful with GET, POST, PUT, FETCH, PATCH, and iPATCH requests and their payload-bearing responses (2.01, 2.03, 3.3. The Q-Block1 Option is used when the client wants to send a large <del> amount of data to the server using the POST, PUT, PATCH, or iPATCH methods where the data and headers do not fit into a single packet. </del>  When Q-Block1 Option is used, the client MUST include a single Request-Tag Option I-D.ietf-core-echo-request-tag.  The Request-Tag value MUST be the same for all of the blocks in the body of data that is being transferred.  It is also used to identify a particular block <del> of a body that needs to be re-transmitted.  The Request-Tag is opaque in nature, but it is RECOMMENDED that the client treats it as an unsigned integer of 8 bytes in length.  An implementation may want to consider limiting this to 4 bytes to reduce packet overhead size. The server still treats it as an opaque entity.  The Request-Tag value MUST be different for distinct bodies or sets of blocks of data and SHOULD be incremented whenever a new body of data is being transmitted between peers.  The initial Request-Tag value SHOULD be randomly generated by the client. For Confirmable transmission, the server MUST continue to acknowledge each packet. </del>  Each individual payload of the body is treated as a new request (see token). server MUST NOT use the same ETag value for different representations of a resource. <del> The ETag is opaque in nature, but it is RECOMMENDED that the server treats it as an unsigned integer of 8 bytes in length.  An implementation may want to consider limiting this to 4 bytes to reduce packet overhead size.  The client still treats it as an opaque entity.  The ETag value MUST be different for distinct bodies or sets of blocks of data and SHOULD be incremented whenever a new body of data is being transmitted between peers.  The initial ETag value SHOULD be randomly generated by the server. </del>  If the client detects that some of the payloads are missing, the missing payloads are requested by issuing a new GET, POST, PUT,

Hello Med, hello Jon, here's a few concrete points I'd like to suggest for new-block: Applicability: I'd have expected to read something like this in the introduction: Separation of layers, sub-topic "congestion control": It should be possible to phrase all congestion control parts of this in a dedicated section (which may also make sense as an appendix). I'd avoid all other mentions of things like PROBINGRATE: For example, Section 3.4 right in the middle of a paragraph on re-requesting missing blocks states that Yes it is, but so is every single CoAP request until the client hears back from the server. Repeating these things in places where are not a new requirement may make it easier for some implementers that try to build the whole stack in a single go, but even for them is prone to the authors missing a spot -- and for everyone else this will each time trigger the question of "is this new here or isn't this already handled by a component two layers down the stack?". I haven't tracked every single retransmission and rate limiting statement throughout the document, but I expect that this section could boil down to something like (The latter replaces MAXPAYLOADS, and I'm not sure whether it is better to express this in terms of package count or bytes on the wire, just giving an example here. All numbers in the above were pulled out of uninformed air.) Separation of layers, sub-topic "Tokens": Same thing, next layer. Whenever you're tempted to talk of a token, consider some of these replacement phrases as a first step: "MUST be sent with a new token" -> "is a new request". "Tokens MUST be included" -> (nothing -- transports use tokens by construction) "MUST be sent with the same token as the response" -> "is sent as a response to" / "is sent as an additional response to that request". (Here it may make sense to refer to the tokens in an additional " (which means it uses the same token, the same way an observation response uses the requests's token for multiple responses)"). Naming: It's technically a minor thing, but people have already complained to me about how hard the Block[12] names are to comprehend, and introducing these options as Block[34] would not help here. I'd like to suggest QuickBlock-Block[12]. (I know that this part of designing a new option is annoying. In the interest of winding up with something that can be learned easily, it is unfortunately essential). In connection with that, it may make sense to briefly think about a draft name before it is submitted as a WG draft. new-block sounds like a 7959bis, which in my understanding this does not aim to be. 4.TBA3 Missing Payloads: I don't quite see why this needs a distinct code. 4.08 Request Entity Incomplete sounds perfectly suitable to me. If you think that sending an existing 4.xx code in the middle of a block-wise transfer would cancel the transfer, there's still two ways out of this: You're just defining what a block-wise transfer is; just allow it. (In a RFC7959 block-wise transfer that runs over a proxy, the proxy may be currently incapable of doing any forwarding and return 5.03 Service Unavailable Max-Age:5. The client would then just pause 5 seconds and send the latest block again.) For all but the last block, it may also be an option to send it as a payload to a 2.31 code -- I don't think that would be outright forbidden (and at any rate, all involved clients speak the protocol anyway).
We don't have an objection to this proposal. We asked the Chairs for guidance before we submitted -00 with "new-block" instead or "quick-block". This one is thus closed.

Note that the same performance benefits can be applied to Confirmable messages if the value of NSTART is increased from 1 (Section 4.7 of  <ins> RFC7252).  However, the use of Confirmable messages will not work if there asymmetrical packet loss.  Some sample examples with Confirmable messages are provided in CON. </ins> There is little, if any, benefit of using these options with CoAP running over a reliable connection RFC8323.  In this case, there is 1.2.  <ins> This document adds a media type for the 4.08 (Request Entity Incomplete) response defining an additional message format for reporting on payloads using the Q-Block1 Option that are not received by the server. </ins> See code for more details. The formatting of this table follows the one used in Table 4 of RFC7252 (Section 5.10).  The C, U, N, and R columns indicate the properties Critical, Unsafe, NoCacheKey, and Repeatable defined in  <ins> Section 5.4 of RFC7252.  Only Critcal and Unsafe columns are marked for the Q-Block1 Option.  Critical, Unsafe, and Repeatable columns are marked for the Q-Block2 Option. </ins> The Q-Block1 and Q-Block2 Options can be present in both the request and response messages.  The Q-Block1 Option pertains to the request The Content-Format Option applies to the body, not to the payload (i.e., it must be the same for all payloads of the same body).  <ins> Q-Block1 Option is useful with the payload-bearing POST, PUT, FETCH, PATCH, and iPATCH requests and their responses (2.01 and 2.04). </ins> Q-Block2 Option is useful with GET, POST, PUT, FETCH, PATCH, and iPATCH requests and their payload-bearing responses (2.01, 2.03, 3.3. The Q-Block1 Option is used when the client wants to send a large  <ins> amount of data to the server using the POST, PUT, FETCH, PATCH, or iPATCH methods where the data and headers do not fit into a single packet. </ins> When Q-Block1 Option is used, the client MUST include a single Request-Tag Option I-D.ietf-core-echo-request-tag.  The Request-Tag value MUST be the same for all of the blocks in the body of data that is being transferred.  It is also used to identify a particular block  <ins> of a body that needs to be re-transmitted.  The Request-Tag is opaque, the server still treats it as opaque but the client SHOULD ensure that it is unique for every different body of transmitted data. It is suggested that the client treats the Request-Tag as an unsigned integer of 8 bytes in length.  An implementation may want to consider limiting this to 4 bytes to reduce packet overhead size.  The initial Request-Tag value SHOULD be randomly generated and then subsequenty incremented by the client whenever a new body of data is being transmitted between peers. For Confirmable transmission, the server continues to acknowledge each packet, but a response is not required (whether separate or piggybacked) until retransmission or successful receipt of the body. </ins> Each individual payload of the body is treated as a new request (see token). server MUST NOT use the same ETag value for different representations of a resource.  <ins> The ETag is opaque, the client still treats it as opaque but the server SHOULD ensure that it is unique for every different body of transmitted data. It is suggested that the server treats the ETag as an unsigned integer of 8 bytes in length.  An implementation may want to consider limiting this to 4 bytes to reduce packet overhead size. The initial ETag value SHOULD be randomly generated and then subsequenty incremented by the server whenever a new body of data is being transmitted between peers. </ins> If the client detects that some of the payloads are missing, the missing payloads are requested by issuing a new GET, POST, PUT,


1. <del> Words... </del>  This document describes a method of encapsulation for binary HTTP messages BINARY using Hybrid Public Key Encryption (HPKE; HPKE).  2. 5.  5.1.  5.2.  5.3. <del> 5.4. </del>  6.

A first cut at the intro and the text describing how different entities might think about each other. After all this, I'm running short on stuff that might go in security considerations. Maybe we should move this new text there so that the security people can find what they need under a familiar heading.
This also needs to talk about how different entities might authenticate others that are involved in order to back that trust with something more concrete. Spamming/DoS: request resources trust proxy resources not to pass on spam; same for target resources and request resources. A request resource might want to authenticate a proxy resource so that they can limit the proxies they accept. A target resource might do the same to request resources, but a more plausible deployment model is those two being the same entity (something that you can't have with proxy/request). Information protection: clients trust proxy resources not to give their information to request resources. That is, not their IP address, nor any strong indication that two requests come from the same entity. (We have seen cases where people think this might be required for anti-abuse, but I think that ignores the spamming/DoS relationship to the detriment of user privacy. This might be a fun discussion.)
We need to explain the advantages of this over making a new connection via a proxy for every request. That is largely performance-related: TLS costs a lot more than this does, both in terms of round trips (1 extra), in terms of bytes exchanged (waaay more), and in terms of CPU cycles spent doing crypto (2x at least).

1.  <ins> The act of making a request using HTTP reveals information about the client identity to a server.  Though the content of requests might reveal information, that is information under the control of the client.  In comparison, the source address on the connection reveals information that a client has only limited control over. Even where an IP address is not directly attributed to an individual, the use of an address over time can be used to correlate requests. Servers are able to use this information to assemble profiles of client behavior, from which they can make inferences about the people involved.  The use of persistent connections to make multiple requests improves performance, but provides servers with additional certainty about the identity of clients in a similar fashion. Use of an HTTP proxy can provide a degree of protection against servers correlating requests.  Systems like virtual private networks or the Tor network Dingledine2004, provide other options for clients. Though the overhead imposed by these methods varies, the cost for each request is significant.  Preventing request linkability requires that each request use a completely new TLS connection to the server. At a minimum, this requires an additional round trip to the server in addition to that required by the request.  In addition to having high latency, there are significant secondary costs, both in terms of the number of additional bytes exchanged and the CPU cost of cryptographic computations. </ins> This document describes a method of encapsulation for binary HTTP messages BINARY using Hybrid Public Key Encryption (HPKE; HPKE). <ins> This protects the content of both requests and responses and enables a deployment architecture that can separate the identity of a requester from the request. Though this scheme requires that servers and proxies explicitly support it, this design represents a performance improvement over options that perform just one request in each connection.  With limited trust placed in the proxy (see trust), clients are assured that requests are not uniquely attributed to them or linked to other requests. </ins> 2. 5. <ins> In this design, a client wishes to make a request of a server that is authoritative for the oblivious target resource.  The client wishes to make this request without linking that request with either: The identity at the network and transport layer of the client (that is, the client IP address and TCP or UDP port number the client uses to create a connection). Any other request the client might have made in the past or might make in the future. In order to ensure this, the client selects a proxy (that serves the oblivious proxy resource) that it trusts will protect this information by forwarding the encapsulated request and response without passing the server (that serves the oblivious request resource). In this section, a deployment where there are three entities is considered: A client makes requests and receives responses A proxy operates the oblivious proxy resource A server operates both the oblivious request resource and the oblivious target resource To achieve the stated privacy goals, the oblivious proxy resource cannot be operated by the same entity as the oblivious request resource.  However, colocation of the oblivious request resource and oblivious target resource simplifies the interactions between those resources without affecting client privacy. </ins> 5.1. <ins> Clients have the fewest direct responsibilities, though clients do need to ensure that they do not undermine the process. Clients cannot carry connection-level state between requests as they only establish direct connections to the proxy responsible for the oblivious proxy resource.  However, clients need to ensure that they construct requests without any information gained from previous requests.  Otherwise, the server might be able to use that information to link requests.  Cookies COOKIES are the most obvious feature that MUST NOT be used by clients.  However, clients need to include all information learned from requests, which could include the identity of resources. Clients also need to ensure that they correctly generate a new HPKE context for every request, using a good source of entropy (RANDOM). Key reuse not only risks linkability, but it could expose request and response contents to the proxy. Clients constructing the request that is to be encapsulated need to avoid including identifying information.  Similarly, the request that is sent to the oblivious request resource, though this request can contain only minimal information as it only needs to include a method and the oblivious request resource URL. </ins> 5.2. <ins> The proxy that serves the oblivious proxy resource has a very simple function to perform.  It forwards messages received at this resource to the oblivious request resource, and forwards responses from the oblivious request resource back to clients.  The proxy MUST forward response status codes without modification. The proxy MUST NOT add information about the client identity when forwarding requests.  This includes the Via field, the Forwarded field FORWARDED, and any similar information. 5.2.1. As there are privacy benefits from having a large rate of requests forwarded by the same proxy (see ta), servers that operate the oblivious request resource might need an arrangement with proxies. This arrangement might be necessary to prevent having the large volume of requests being classified as an attack by the server. If a server does accept a large volume of requests from a proxy, it needs to trust that the proxy does not allow abusive levels of request volumes from clients.  That is, if a server allows requests from the proxy to be exempt from rate limits, the server might want to ensure that the proxy applies similar rate limiting when receiving requests from clients. Servers that enter into an agreement with a proxy that enables a higher request rate might choose to authenticate the proxy to enable the higher rate. 5.2.2. As the time at which encapsulated request or response messages are sent can reveal information to a network observer.  Though messages exchanged between the oblivious proxy resource and the oblivious request resource might be sent in a single connection, traffic analysis could be used to match messages that are forwarded by the proxy. A proxy could, as part of its function, add delays in order to increase the anonymity set into which each message is attributed. This could latency to the overall time clients take to receive a response, which might not what some clients want. A proxy can use padding to reduce the effectiveness of traffic analysis. A proxy that forwards large volumes of exchanges can provide better privacy by providing larger sets of messages that need to be matched. </ins> 5.3.  <ins> A server that operates both oblivious request and oblivious target resources is responsible for removing request encapsulation, generating a response the encapsulated request, and encapsulating the response. Servers should account for traffic analysis based on response size or generation time.  Techniques such as padding or timing delays can help protect against such attacks; see ta. If separate entities provide the oblivious request resource and oblivious target resource, these entities might need an arrangement similar to that between server and proxy for managing denial of service; see dos.  It is also necessary to provide confidentiality protection for the unprotected requests and responses, plus protections for traffic analysis; see ta. </ins> 6.


protected content.  response describes the process for constructing and processing an Encapsulated Response.  4.1. Clients encapsulate a request "request" with an HPKE public key Compute an HPKE context using "pkR", yielding "context" and encapsulation key "enc". <del> Construct additional associated data, "aad", by prepending a single byte with a value of 0x01 to the key identifier.  The key identifier length is not included in the AAD. </del> Encrypt (seal) "request" with "keyID" as associated data using "context", yielding ciphertext "ct". Concatenate the length of "keyID" as a variable-length integer, <del> "keyID", "enc" and "ct", yielding an Encapsulated Request "enc_request". </del>  In pseudocode, this procedure is as follows: Parses "enc_request" into "keyID", "enc", and "ct" (indicated using the function "parse()" in pseudocode).  The server is then able to find the HPKE private key, "skR", corresponding to <del> "keyID". </del>  Compute an HPKE context using "skR" and the encapsulated key "enc", yielding "context". <del> Construct additional associated data, "aad", by prepending a single byte with a value of 0x01 to the key identifier. </del>  Decrypt "ct" using "aad" as associated data, yielding "request" or <del> an error on failure. </del>  In pseudocode, this procedure is as follows: "enc_response" as follows: Export a secret "secret" from "context", using the string <del> "response" as a label.  The length of this secret is "Nsk" - the length of the secret assocated with "context". </del>  Extract a pseudorandom key "prk" using the "Extract" function provided by the KDF algorithm associated with "context".  The <del> "ikm" input to this function is "secret"; the "salt" input is "request". </del>  Use the "Expand" function provided by the same KDF to extract an AEAD key "key", of length "Nk" - the length of the keys used by length "Nn" - the length of the nonce used by the AEAD. Generating "nonce" uses a label of "nonce". <del> Construct additional associated data "aad", that consists of a single byte with a value of 0x02. </del> Encrypt "response", passing the AEAD function Seal the values of <del> "key", "nonce", "aad", and a "pt" input of "request", which yields "enc_response". </del>  In pseudocode, this procedure is as follows: Clients decrypt an Encapsulated Request by reversing this process. <del> That is, clients follow the same process to derive values for "key", "nonce", and "aad".  The client then decrypts the Encapsulated Response using the Open function provided by the AEAD.  Decrypting might produce an error, as shown. </del>  4.3.

Makes some of my suggestions from , and addresses in the process. For context, I consider the variable to be the wire-encoded (length prefixed) thing, and I tried to clarify that here. I don't feel strongly about the way that's written, but I do think it's important that everything sent on the wire is authenticated, including the keyID length.
Should the key ID length be explicitly authenticated, e.g., by including it in the AAD, or should the AEAD implicitly authenticate things? Unclear!
Should we even bother with an AAD at all? The best reason is that the keyID determines which key the server uses, which is information that factors into decisions. (A related question might be why doesn't HPKE take variables as input so that things like key identifiers can be integrated into the key schedule.)
My take: yes. I need to think through the implications of no additional authentication at all, and in the mean time, I'd be more comfortable with simply authenticating everything possible. I think it was discussed, but it makes the interface a mess. And since applications can accomplish the same thing by shoving what they want authenticated into the AAD, it was voted down.
Yeah, you and I both know that putting stuff in the AAD isn't a real substitute for having it in the key schedule. I completely understand how this would mess with the purity of the design, but TLS managed by wrapping its labels better (which also addresses a known problem with HKDF not being injective).
Fixed by virtue of making the key ID fixed length in .
In our discussion of , NAME and I explored the ways in which nonce reuse might occur. The problem arises if the client reuses . This leads to nonce reuse on the request for sure. However, if the request is the same, the problem shifts to the response. Unless the response is also identical, we get nonce reuse on the response instead. We then discussed options for safeguarding against this. As the client is expected to include randomness in its derivation of its key, it seems like the failing is not something that adding extra steps at the client will address. So I don't think that adding anything to the request really helps. Separately, HPKE code is supposed to be stateful. Reuse of a context should result in the sequence number increasing, leading to a nonce that the server cannot reconstruct (unless it also counts and does trial decryption, but that's two bad actors). That should ensure that the client doesn't use the same nonce twice. You really have to have bad randomness at the client to get into a deliberate nonce reuse scenario if you trust that the HPKE implementation is properly stateful. However, a response that is generated in response to a replayed request is something I am concerned about. We know that HTTP clients routinely do, even if the request is marked POST. So some protection here is warranted. For this, I'm going to suggest that we change from salting based on the request to salting based on . Hashing the entire message is likely to be very expensive, both in terms of cycles, but also in terms of state. The public key should be enough to ensure the binding in the case where a client doesn't reuse the context, and the new randomness should help in case of reuse. I think that it's OK to use 128 bits of extra randomness here, but we don't have a handy constant to hang that on. Nn is 96, Nk could be 128 or 256 depending on the AEAD. What we really want is the block size, but that isn't a property that is exposed anywhere.
I think this is the right design on balance. If we were more conservative, we could include the entire client request (including ), but that doesn't really hedge against the misuse scenario. I'll propose text in .
Fixed in .

protected content.  response describes the process for constructing and processing an Encapsulated Response. <ins> The size of the Nonce field in an Encapsulated Response corresponds to the size of an AEAD key for the corresponding HPKE ciphersuite. </ins> 4.1. Clients encapsulate a request "request" with an HPKE public key Compute an HPKE context using "pkR", yielding "context" and encapsulation key "enc".  Encrypt (seal) "request" with "keyID" as associated data using "context", yielding ciphertext "ct". Concatenate the length of "keyID" as a variable-length integer,  <ins> "keyID", "enc", and "ct", yielding an Encapsulated Request "enc_request".  Note that "enc" is of fixed-length, so there is no ambiguity in parsing "enc" and "ct". </ins> In pseudocode, this procedure is as follows: Parses "enc_request" into "keyID", "enc", and "ct" (indicated using the function "parse()" in pseudocode).  The server is then able to find the HPKE private key, "skR", corresponding to  <ins> "keyID".  If no such key exists, the server returns an error. </ins> Compute an HPKE context using "skR" and the encapsulated key "enc", yielding "context".  <ins> Construct additional associated data, "aad", as the Key Identifier "keyID" from "enc_request". </ins> Decrypt "ct" using "aad" as associated data, yielding "request" or  <ins> an error on failure.  If decryption fails, the server returns an error. </ins> In pseudocode, this procedure is as follows: "enc_response" as follows: Export a secret "secret" from "context", using the string  <ins> "response" as a label.  The length of this secret is "Nk" - the length of an AEAD key assocated with "context". Generate a random value of length "max(Nn, Nk)" bytes, called "response_nonce". </ins> Extract a pseudorandom key "prk" using the "Extract" function provided by the KDF algorithm associated with "context".  The  <ins> "ikm" input to this function is "secret"; the "salt" input is the concatenation of "enc" (from "enc_request") and "response_nonce" </ins> Use the "Expand" function provided by the same KDF to extract an AEAD key "key", of length "Nk" - the length of the keys used by length "Nn" - the length of the nonce used by the AEAD. Generating "nonce" uses a label of "nonce".  Encrypt "response", passing the AEAD function Seal the values of  <ins> "key", "nonce", empty "aad", and a "pt" input of "request", which yields "ct". Concatenate "response_nonce" and "ct", yielding an Encapsulated Response "enc_response".  Note that "response_nonce" is of fixed- length, so there is no ambiguity in parsing either "response_nonce" or "ct". </ins> In pseudocode, this procedure is as follows: Clients decrypt an Encapsulated Request by reversing this process.  <ins> That is, they first parse "enc_response" into "response_nonce" and "ct".  They then follow the same process to derive values for "aead_key" and "aead_nonce".  Finally, the client decrypts "ct" using the Open function provided by the AEAD.  Decrypting might produce an error, as shown. </ins> 4.3.


It is possible for a server to be configured with multiple Oblivious Proxy Resources, each for a different Oblivious Request Resource as <del> needed. </del>  9.3.

Truly, the most interesting forwarding is what occurs at the Oblivious Request Resource, but this is a point of inflexibility that some people struggle with. No point in hiding how we might intend for a generic proxy to operate. The alternatives people invent are likely to be worse if we don't at least point in the rough direction of a good solution.
Resource and the Oblivious Request Resource. This means that any encapsulated request sent to the Oblivious Proxy Resource will always be forwarded to the Oblivious Request Resource. This constraint was imposed to simplify proxy configuration and mitigate against the Oblivious Proxy Resource being used as a generic proxy for unknown Oblivious Request Resources. The proxy will only forward for Oblivious Request Resources that it has explicitly configured and allowed. This seems like it's pretty inflexible. I wonder if maybe a compromise would be some kind of URL pattern?
I agree that it's written as very inflexible — I'd be happy to see this change for wording. I've personally interpreted this, though, to mean that the mapping could coincide with a URI template, but it's up to the proxy of what to do. So, one proxy could say: maps to But another could say: maps to Both of these are 1:1 technically. The latter case needs to be careful that it has correct ACLs to not allow arbitrary access, but it's still a mapped resource.
Yes, I think this explanation does a lot to clarify the possible approaches.

It is possible for a server to be configured with multiple Oblivious Proxy Resources, each for a different Oblivious Request Resource as  <ins> needed.  If the goal is to support a large number of Oblivious Request Resources, clients might be provided with a URI template TEMPLATE, from which multiple Oblivious Proxy Resources could be constructed. </ins> 9.3.


BCP 14 RFC2119 RFC8174 when, and only when, they appear in all capitals, as shown here.  An HTTP request that is encapsulated in an HPKE-encrypted message; see request. it trusts the oblivious proxy resource to remove, such as fields that are listed in the Connection header field.  The oblivious proxy resource interacts with the oblivious request <del> resource by constructing a request using the same restrictions as the client request, except that the target URI is the oblivious request resource.  The content of this request is copied from the client. The oblivious proxy resource MUST NOT add information about the client to this request. </del>  When a response is received from the oblivious request resource, the oblivious proxy resource forwards the response according to the rules

It would be wrong to use "user agent" as this could be used for an HTTP request made by any client toward any server (using the HTTP definitions).
Why don't use "Oblivious Client" and the "OC" acronym, like OAuth does with "Authorization Server"? This would preserve the natural "client" meaning, and could make the document more readable. The same acronym trick could ease readability wrt "Oblivious Request Resource" and "Oblivious Target Resource"...
I know that people like acronyms, but it doesn't really solve this problem. The oblivious HTTP client really is an HTTP client in the sense that HTTP knows; calling it anything else would be more confusing, I think. As it seems like this is a case where more words would help. I've added more words.
Since there are so many occurrencies of I think that's ok :) Probably in the Introduction, "client" means "HTTP client", but anyway the difference is clear to me now :D
since there are various layers, the term "client" can be applicable to both the oblivious proxy/request resource. Maybe the term User agent can be appropriate when we refer to the originating client?
Hi Roberto, Does URL clarify things? I think that "client" still makes a lot of sense here, but you are right that this is not an HTTP client in the strictest sense. (Although, now that I write this, it really is, it's just that this uses something other than a connection as a medium from getting a request to the server...)
LGTM

BCP 14 RFC2119 RFC8174 when, and only when, they appear in all capitals, as shown here. <ins> This document uses its own definition of client.  When referring to the HTTP definition of client (Section 3.3 of HTTP), the term "HTTP client" is used; see http-usage. </ins> An HTTP request that is encapsulated in an HPKE-encrypted message; see request. it trusts the oblivious proxy resource to remove, such as fields that are listed in the Connection header field. <ins> The client role in this protocol acts as an HTTP client both with respect to the oblivious proxy resource and the oblivious target resource.  For the request the clients makes to the oblivious target resource, this diverges from typical HTTP assumptions about the use of a connection (see Section 3.3 of HTTP) in that the request and response are encapsulated rather than sent over a connection.  The oblivious proxy resource and the oblivious request resource also act as HTTP clients toward the oblivious request resource and oblivious target resource respectively. </ins> The oblivious proxy resource interacts with the oblivious request  <ins> resource as an HTTP client by constructing a request using the same restrictions as the client request, except that the target URI is the oblivious request resource.  The content of this request is copied from the client.  The oblivious proxy resource MUST NOT add information about the client to this request. </ins> When a response is received from the oblivious request resource, the oblivious proxy resource forwards the response according to the rules


encapsulated request: a method of POST, a target URI of the oblivious proxy resource, a header field containing the content type (see (media-types), and the encapsulated request as the request content. <del> Clients MAY include fields that do not reveal information about the content of the request, such as Alt-Used ALT-SVC, or information that it trusts the oblivious proxy resource to remove, such as fields that are listed in the Connection header field. </del>  The client role in this protocol acts as an HTTP client both with respect to the oblivious proxy resource and the oblivious target

cc NAME
Alt-Used sticks out to me. So I looked for whether Alt-Svc is some prerequisite for oblivious HTTP and it doesn't seem so. I'm not sure many folks would be that familiar with Alt-Used, ? Is there some other, more familiar, filed that you could use as an example?

encapsulated request: a method of POST, a target URI of the oblivious proxy resource, a header field containing the content type (see (media-types), and the encapsulated request as the request content.  <ins> In the request to the oblivious proxy resource, clients MAY include additional fields.  However, those fields MUST be independent of the encapsulated request and MUST be fields that the oblivious proxy resource will remove before forwarding the encapsulated request towards the target, such as the Connection or Proxy-Authorization header fields SEMANTICS. </ins> The client role in this protocol acts as an HTTP client both with respect to the oblivious proxy resource and the oblivious target


forwarding requests that might be used to identify clients, with the exception of information that a client is aware of.  A relay MAY add information to requests if the client is aware of the nature of the information that could be added.  The client does not need to be aware of the exact value added for each request, but needs to know the range of possible values the relay might use.  It is important to note that information added by the relay can reduce the <del> size of the anonymity set of clients at a server. A relay can also generate responses, though it assumed to not be able to examine the content of a request (other than to observe the choice of key identifier, KDF, and AEAD), so it is also assumed that it cannot generate an Encapsulated Response. </del>  <del> 7.2.1. </del>  As there are privacy benefits from having a large rate of requests forwarded by the same relay (see ta), servers that operate the higher request rate might choose to authenticate the relay to enable the higher rate. <del> 7.2.2. </del>  This document assumes that all communication between different entities is protected by HTTPS.  This protects information about 9.2. This protocol assumes a fixed, one-to-one mapping between the <del> Oblivious Proxy Resource and the Oblivious Gateway Resource.  This </del>  means that any encrypted request sent to the Oblivious Relay Resource will always be forwarded to the Oblivious Gateway Resource.  This constraint was imposed to simplify relay configuration and mitigate allowed. It is possible for a server to be configured with multiple Oblivious <del> Proxy Resources, each for a different Oblivious Gateway Resource as </del>  needed.  If the goal is to support a large number of Oblivious Gateway Resources, clients might be provided with a URI template TEMPLATE, from which multiple Oblivious Relay Resources could be

This is a lot of words to explain the point, so I'm happy to take simplifying suggestions. cc NAME
Changes look good to me. I also updated Section 4.1 of URL to demonstrate how rate-limiting will not impact the privacy of benign clients.
To address the scenario of the target giving feedback to the gateway, I introduced a new header "Ohttp-Outside-Encap". The "Ohttp-Outside-Encap" header is added by the Oblivious request resource to the HTTP request to signal to the Oblivious target resource the list of header fields that it will be remove from the HTTP response. Please see Section 7 in URL for more details.
I think that we want some extra text here, probably before the last sentence about clients understanding the extent to which they might be treated differently. I don't know if this is worth adding, but a relay acting on the HTTP Retry-After header field is a great example of something that might destroy anonymity. ... and now I think we have enough material for a new section.
Applied NAME suggested text (as an addendum to the main content here, not inserted in the middle) and moved everything -- including proxies applying differential treatment to requests -- to a new subsection. Thanks, all!
Something that came up during Vienna during the rate limiting topic is how these signals are consumed and acted upon by proxies. We know that the proxy sending additional bits per client might allow the target to partition the anonymity set to detrimental effect. But we haven't fully explored how target->proxy signals, like rate limits, are consumed and applied. Generally speaking, I think that proxies need to act on any target->proxy signals independently of client requests, as otherwise a target can use this signal to try and partition the anonymity set. That means, for example, that a proxy should not apply rate limits to just one bad-behaving client, but apply limits uniformly across all client requests.
Do you mean the oblivious request resource -> oblivious proxy resource hop? The target can't communicate with the proxy; anything it sends is encapsulated (which is why Tiru wanted a new header field that breaks out of that encapsulation). The most obvious example (see ) is that a particular request is identified as abusive somehow. Letting the proxy know, so that it might treat that client differently, is the entire goal of that process. And I don't think that there is any inherent risk of that being tied to an individual request. Though I think that this is unlike the CDN reputation case where a set of attributes is forwarded along with a request; the goal here is to have the proxy do the extra work of offloading requests by blocking or slowing them. I guess that slowing requests might have an observable effect through the timestamps. There is a second piece, which is not request-related. A server might become overloaded and need to tell the proxy to slow down in the aggregate. A holistic signal makes sense there.
Surely the target can communicate with the proxy -- it just adds a header, just like Tiru did. Yes, I understand the goal, but I'm saying that goals runs contrary to the competing privacy goal of OHTTP, which is to maintain client<>request unlinkability. As a simple example, consider the following scenario. There are three clients C1, C2, and C3 sending requests to a target through a proxy in rounds. In each round, the target can guess which request corresponds to which client with some probability. Absent any information about the client, the target guesses correctly with probability 1/3. Now let's assume the proxy flags one request from one client Ci in round j with the shadowban bit. The target, in response, decides it's going to apply some rate limit or otherwise ask the proxy to treat the client differently. And let's say it does that by banning Ci from sending a request in round j+1. Now, in round j+1, the target sees only two requests. If all requests were unlinkable, the probability that the target could correctly guess the client for each request in j+1 and j would be 1/9 (=1/3 * 1/3). But that's not the case anymore, since the target knows the requests in j+1 correspond to the unflagged requests in round j. This is all pretty farfetched, but I think the core idea is simply that the proxy allowed the target to partition the anonymity set by applying per-client actions at request of the target. Balancing abuse and privacy here seems pretty challenging.
The response from the target will be encapsulated, so new headers will be hidden from the proxy. What Tiru was suggesting was that we teach the response resource to recognize a header that is not encapsulated, but copied to the outer envelope instead. Isn't this exactly the sort of thing that we're warning about when we say that every bit can split the client population in half? That speaks to a similar restriction on per-response entropy as exists on requests. The question whether this is orthogonal (and additive) or correlated (and therefore not able to divide the client population again).
Yes, I'm saying this header is not encapsulated. Well, sort of. Perhaps restricting per-response entropy will help, but I think this needs more analysis. In any case, if the proxy does not treat client requests independently of what information it learns from the target, then things start becoming correlated. I'd prefer we not just overlook this relationship as we reason about (a) what information proxies (and targets) can send to targets (and proxies, respectively), and (b) how the recipient of that entity uses the information. As of now, I think applying per-client restrictions to requests upon being signaled from the target is harmful (see scenario described above).
We updated draft-rdb-ohai-feedback-to-proxy to handle both server overload and malicious clients attacking the server scenarios. The latter case is tricky as it can be potentially abused to identify a client. We proposed the following changes to address this attack: 1: Indicates that RateLimit fields are applicable to all the clients that are serviced by the same Oblivious proxy. 2: Indicates that RateLimit fields are applicable only to the offending client. For example, this value is used if the client is attacking the server (e.g., the client is using an abnormal header that matches an attack pattern). The Oblivious proxy can shadowban requests from the offending client for a certain duration instead of rate-limiting the requests when the client has a high ratio of malicious requests to legitimate requests.
The second value of the "ohttp-target" parameter seems to be the problematic case here, as described earlier in this issue. NAME do you think it's safe (from a client privacy perspective) for the proxy to change its behavior on a per-client basis?
Yes, the second value can be potentially abused by the target. However, the proxy does not immediately act on the second value to rate-limit the traffic from the client but starts maintaining a count of responses to the client with "ohttp-target" parameter set to 2 (potential malcious-requests) and responses without the parameter (legitimate-requests). If the client has a high ratio of malicous-requests to legitimate-requests, it can shadow requests from the offending client for certain duration. A typical botnet attacking the server would not send a single malicious request but multiple requests from the same client and from multiple clients to overload the server. The target has no clue if the requests are coming from the same client or different clients and the proxy is using the second value only as a hint to determine the client reputation score and act accordingly at a later time. Do you think the proposed mechanism is safe to protect the client privacy or it can possibly be abused by the target ?
So I'm seeing some fairly positive things in the new version of the feedback draft. What I think we should do is first take this discussion to the mailing list, but then talk about whether just providing rate limiting signals is the right approach or whether a more generic communication path needs to be established. Rate limiting does allow us to address a good number of the use cases we have identified so far, but it could be constraining if we find that request resources need to be updated piecemeal to enable new use cases later. A more generic signaling scheme might relieve some of that pressure. It might be that all we need is a negotiation system whereby the request resource signals what it is willing to keep outside of encapsulation and the target then uses those. Given likely deployment scenarios, that might work even without signaling in some cases, but a more explicit scheme might be better for interoperability.
No, I don't, as . I don't think the question is whether rate limits are sufficient for the use cases we care about. As described , the relevant question here seems to be whether the signals from target to proxy -- whatever they may be, and however they may be sent -- can be used to further partition the client anonymity set.
Fair. So what does a system that looks good look like? Do we have to frame differential treatment in terms of things that the client accepts, just like we do for added information? Because we might frame differential treatment as being roughly equated to adding information to requests.
This would be a reasonable framing, yeah. Something something "if you misuse this proxy, you run the risk of revealing information to the target"?
In your example of three clients, the proxy does not rate-limit the requests from client C1 based on a single feedback from proxy. The proxy will block traffic from C1 only after it sees such a feedback signal for multiple requests from C1. Assuming the threshold is 10 requests, the probability score will be (0.000016) to send successive 10 feedback signals to C1. The mechanism only works if the target sees an attack pattern or garbage data in multiple requests from C1. An legitimate client will never send requests which are linkable unlike a malicious client which will send malformed requests.
NAME Well, this is different from the example I proposed. Nevertheless, I'm not convinced this changes the situation in any meaningful way. I think we need to be clear about the risks here, and stating them in a way like NAME proposed seems like a good way to do that.
Agreed, I was trying to show the proposed mechanism does not adversely impact the privacy of legitimate clients.
Sounds good, we can introduce a new header (e.g., h=header1:header2:header3) for the request resource to signal that it will keep header1, header2 and header3 outside of the encapsulation so the target can decide to use those headers. RateLimit-Limit can be one of the headers to start with.
Sorry, but I don't think this is true. I'm saying that we've not demonstrated this to be the case, and the burden is on us to do so if we are to recommend it in the spec.
Sure, the onus will anyway be on draft-rdb-ohai-feedback-to-proxy to prove it is privacy preserving.
This is good. It gives us a basis for thinking about how feedback might work. I don't know if you need to clarify the target->gateway->relay (target->request->proxy) feedback path though. It seems like the distinction between target and gateway is a bit muddy here.Approved, once the terminology aligns

forwarding requests that might be used to identify clients, with the exception of information that a client is aware of. <ins> Finally, a relay can also generate responses, though it assumed to not be able to examine the content of a request (other than to observe the choice of key identifier, KDF, and AEAD), so it is also assumed that it cannot generate an Encapsulated Response. 7.2.1. </ins> A relay MAY add information to requests if the client is aware of the nature of the information that could be added.  The client does not need to be aware of the exact value added for each request, but needs to know the range of possible values the relay might use.  It is important to note that information added by the relay can reduce the  <ins> size of the anonymity set of clients at a gateway. Moreover, relays MAY apply differential treatment to clients that engage in abusive behavior, e.g., by sending too many requests in comparison to other clients, or as a response to rate limits signalled from the gateway.  Any such differential treatment can reveal information to the gateway that would not be revealed otherwise and therefore reduce the size of the anonymity set of clients using a gateway.  For example, if a relay chooses to rate limit or block an abusive client, this means that any client requests which are not treated this way are known to be non-abusive by the gateway.  Clients should consider the likelihood of such differential treatment and the privacy risks when using a relay. Some patterns of abuse cannot be detected without access to the request that is made to the target.  This means that only the gateway or target are in a position to identify abuse.  A gateway MAY send signals toward the relay to provide feedback about specific requests. A relay that acts on this feedback could - either inadvertently or by design - lead to clients being deanonymized. </ins>  <ins> 7.2.2. </ins> As there are privacy benefits from having a large rate of requests forwarded by the same relay (see ta), servers that operate the higher request rate might choose to authenticate the relay to enable the higher rate.  <ins> 7.2.3. </ins> This document assumes that all communication between different entities is protected by HTTPS.  This protects information about 9.2. This protocol assumes a fixed, one-to-one mapping between the  <ins> Oblivious Relay Resource and the Oblivious Gateway Resource.  This </ins> means that any encrypted request sent to the Oblivious Relay Resource will always be forwarded to the Oblivious Gateway Resource.  This constraint was imposed to simplify relay configuration and mitigate allowed. It is possible for a server to be configured with multiple Oblivious  <ins> Relay Resources, each for a different Oblivious Gateway Resource as </ins> needed.  If the goal is to support a large number of Oblivious Gateway Resources, clients might be provided with a URI template TEMPLATE, from which multiple Oblivious Relay Resources could be


Encoding an integer to a sequence of bytes in network byte order is described using the function "encode(n, v)", where "n" is the number <del> of bytes and "v" is the integer value.  The function "len()" returns the length of a sequence of bytes. </del>  Formats are described using notation from QUIC. The client then constructs an Encapsulated Request, "enc_request", from a binary encoded HTTP request, "request", as follows: <del> Compute an HPKE context using "pkR" and a label of "message/bhttp request", yielding "context" and encapsulation key "enc". Construct associated data, "aad", by concatenating the values of </del>  "keyID", "kemID", "kdfID", and "aeadID", as one 8-bit integer and three 16-bit integers, respectively, each in network byte order. <del> Encrypt (seal) "request" with "aad" as associated data using "context", yielding ciphertext "ct". </del>  <del> Concatenate the values of "aad", "enc", and "ct", yielding an </del>  Encrypted Request "enc_request". Note that "enc" is of fixed-length, so there is no ambiguity in that the server is unwilling to use with "skR", the server returns an error. <del> Compute an HPKE context using "skR", a label of "message/bhttp request", and the encapsulated key "enc", yielding "context". </del>  <del> Construct additional associated data, "aad", from "keyID", "kemID", "kdfID", and "aeadID" or as the first seven bytes of "enc_request". </del>  <del> Decrypt "ct" using "aad" as associated data, yielding "request" or an error on failure.  If decryption fails, the server returns an </del>  error. In pseudocode, this procedure is as follows:

We previously put the details from the key configuration (key id, KEM, KDF, AEAD) in the AAD for the request. But NAME noted that this meant that this wasn't bound to the response. Analysis shows that this isn't a security problem, but while that depends on some very reasonable assumptions about how keys are used, there is no reason not to do better. Performance-wise, this change is a wash. The AAD input is now empty, which should make this a tiny bit faster to execute. The downside is that the info is no longer static, which means that it is a tiny bit slower, especially on the server side where it is harder to just pass a constant value into SetupBaseR and the bits from the header into the AAD. But those are extraordinarily trivial differences. The spec doesn't really change much either, though I've taken this chance to be a bit more explicit about what functions in HPKE are run and what their inputs are. I will do examples in a follow-up so that you can see the effect on those (the numbers change, that's all). Code changes are fairly simple also, see URL for an example. Note that the biggest part of this is down to a structural choice, the actual changes are minor. Response handling doesn't change at all.
Section 4.1 seems to incorporates a bunch of information into the computation: However, since that context is in the parameter of , and not the parameter to , that same information doesn't figure into : This is a bit odd because , etc., also apply to the response. Should those be moved to the parameter instead? (Although, of those four fields, I think only authenticating does anything. The three algorithm IDs already figure into the HPKE suite ID. Was the intention to authenticate the instead?)
The intent was to belt and braces this, but yeah, it seems like we missed the braces part. A zero-length AAD is somewhat appealing when we already need to provide an info parameter, this would just make it a configurable one. I'm thinking "message/bhttp request" (the current info string), a 0 byte (to follow patterns elsewhere), and then the current AAD. Then make the AAD zero length. The only thing that gives me pause is that we already have an analysis that supports the current design. That suggests that a tighter design might work, but NAME might know how hard it would be to re-tool for a tweak.
I don't think moving the current AAD to the info parameter has a meaningful improvement beyond aesthetics, so I would be fine with this change. Updating the models should be pretty straightforward. (There is a ProVerif one not yet on GitHub, but I hope it will be soon.) As David points out, the HPKE parameters are already implicitly authenticated by way of agreement on the HPKE context. I would claim the keyID is also implicitly authenticated in this way, since the keyID determines the private key used to produce the shared HPKE context. The exception here being the case where there are two distinct keyID values that correspond to the same private key. In that case, if the response was generated without examining the request, then it would be possible for client and gateway to disagree on the keyID value used. Would this actually happen in practice? Doubtful, but fixing by moving the AAD around does the trick.
Verified .

Encoding an integer to a sequence of bytes in network byte order is described using the function "encode(n, v)", where "n" is the number  <ins> of bytes and "v" is the integer value.  ASCII ASCII encoding of a string "s" is indicated using the function "encode_str(s)".  The function "len()" returns the length of a sequence of bytes. </ins> Formats are described using notation from QUIC. The client then constructs an Encapsulated Request, "enc_request", from a binary encoded HTTP request, "request", as follows:  <ins> Construct a message header, "hdr", by concatenating the values of </ins> "keyID", "kemID", "kdfID", and "aeadID", as one 8-bit integer and three 16-bit integers, respectively, each in network byte order.  <ins> Build "info" by concatenating the ASCII-encoded string "message/ bhttp request", a zero byte, and the header. Create a sending HPKE context by invoking "SetupBaseS()" (HPKE) with the public key of the receiver "pkR" and "info".  This yields the context "sctxt" and an encapsulation key "enc". Encrypt "request" by invoking the "Seal()" method on "sctxt" (HPKE) with empty associated data "aad", yielding ciphertext "ct". </ins>  <ins> Concatenate the values of "hdr", "enc", and "ct", yielding an </ins> Encrypted Request "enc_request". Note that "enc" is of fixed-length, so there is no ambiguity in that the server is unwilling to use with "skR", the server returns an error.  <ins> Build "info" by concatenating the ASCII-encoded string "message/ bhttp request", a zero byte, "keyID" as an 8-bit integer, plus "kemID", "kdfID", and "aeadID" as three 16-bit integers. </ins>  <ins> Create a receiving HPKE context by invoking "SetupBaseR()" (HPKE) with "skR", "enc", and "info".  This produces a context "rctxt". </ins>  <ins> Decrypt "ct" by invoking the "Open()" method on "rctxt" (HPKE), with an empty associated data "aad", yielding "request" or an error on failure.  If decryption fails, the server returns an </ins> error. In pseudocode, this procedure is as follows:


amount of requests it needs to track if it needs to prevent replay attacks. <del> A server can maintain state for requests for a small window of time over which it wishes to accept requests.  The server then rejects requests if the request is the same as one that was previously answered within that time window.  Servers can reject requests outside of this window and signal that clients might retry with a different "Date" header field; see REQUEST-DATE.  Servers can identify duplicate requests using the encapsulation ("enc") value. Servers SHOULD allow for the time it takes requests to arrive from the client, with a time window that is large enough to allow for differences in the clock of clients and servers.  How large a time window is needed could depend on the population of clients that the server needs to serve. Servers MUST NOT treat the time window as secret information.  An attacker can actively probe the server with specially crafted request timestamps to determine the time window over which the server will accept responses. REQUEST-DATE contains further considerations for the use of the "Date" request header field.  This includes the way in which clients might correct for clock skew and the privacy considerations arising from that usage.  Servers that reject requests on the basis of the "Date" request header field SHOULD implement the feedback mechanism in REQUEST-DATE to support clock correction by clients. </del>  7.5. The total number of affected messages affected by server key compromise can be limited by regular rotation of server keys.  8. One goal of this design is that independent client requests are only 11. <del> Please update the "Media Types" registry at </del>  https://www.iana.org/assignments/media-types [1] with the registration information in media-types for the media types "message/ ohttp-req", "message/ohttp-res", and "application/ohttp-keys".  12.  References 12.1.  URIs

This includes the time correction piece. I'm interested in whether people think that it is OK to include that. The section could be removed along with the corresponding IANA piece, but given the prevalence of clock skew, I'm inclined to leave it in.
The picture might help, but it is also a lot of vertical real estate to dedicate to this. Let's see if I can't compress it a little.
Maybe an alternative style is to just list the happy path actions in a list? Client sends request, gets back response with 4xx and date header, retires request with new HPKE context, and then stops based on response, or something. These four simple steps are just spread across a lot of lines right now. But this is purely editorial, so I trust your judgement here.
There is a bunch of stuff that we normatively depend on regarding the use of Date. As it seems like request-date isn't going anywhere, we should pull in the relevant pieces instead.
That sounds reasonable like a reasonable way to unblock us and make forward progress.
Addressed by .
This LGTM. I wonder if it would be helpful to show the retry dance in a picture. Something like:

amount of requests it needs to track if it needs to prevent replay attacks.  <ins> An Oblivious Gateway Resource can maintain state for requests for a small window of time over which it wishes to accept requests.  The Oblivious Gateway Resource can store all requests it processes within this window.  Storing just the "enc" field of a request, which should be unique to each request, is sufficient.  The Oblivious Gateway Resource then rejects requests if the request is the same as one that was previously answered within that time window, or if the "Date" header field from the decrypted request is outside of the current time window. Oblivious Gateway Resources SHOULD allow for the time it takes requests to arrive from the client, with a time window that is large enough to allow for differences in clocks. Oblivious Gateway Resources MUST NOT treat the time window as secret information.  An attacker can actively probe with different values for the "Date" field to determine the time window over which the server will accept responses. 7.4.2. An Oblivious Gateway Resource can reject requests that contain a "Date" value that is outside of its active window with a 400 series status code.  The problem type PROBLEM of "https://iana.org/assignments/http-problem-types#date" is defined to allow the server to signal that the "Date" value in the request was unacceptable. fig-date-reject shows an example response in HTTP/1.1 format. Disagreements about time are unlikely if both client and Oblivious Gateway Resource have a good source of time; see NTP.  However, clock differences are known to be commonplace; see Section 7.1 of CLOCKSKEW. Including a "Date" header field in the response allows the client to correct clock errors by retrying the same request using the value of the "Date" field provided by the Oblivious Gateway Resource.  The value of the "Date" field can be copied if the request is fresh, with an adjustment based on the "Age" field otherwise.  When retrying a request, the client MUST create a fresh encryption of the modified request, using a new HPKE context. Intermediaries can sometimes rewrite the "Date" field when forwarding responses.  This might cause problems if the Oblivious Gateway Resource and intermediary clocks differ by enough to cause the retry to be rejected.  Therefore, clients MUST NOT retry a request with an adjusted date more than once. Oblivious Gateway Resources that condition their responses on the "Date" header field SHOULD either ensure that intermediaries do not cache responses (by including a "Cache-Control" directive of "no- store") or designate the response as conditional on the value of the "Date" request header field (by including the token "date" in a "Vary" header field). Clients MUST NOT use the date provided by the Oblivious Gateway Resource for any other purpose, including future requests to any resource.  Any request that uses information provided by the Oblivious Gateway Resource might be correlated using that information. </ins> 7.5. The total number of affected messages affected by server key compromise can be limited by regular rotation of server keys. <ins> 7.7. Including a "Date" field in requests reveals some information about the client clock.  This might be used to fingerprint clients UWT or to identify clients that are vulnerable to attacks that depend on incorrect clocks. Clients can randomize the value that they provide for "Date" to obscure the true value of their clock and reduce the chance of linking of requests over time.  However, this increases the risk that their request is rejected as outside the acceptable window. </ins> 8. One goal of this design is that independent client requests are only 11.  <ins> IANA are request to update the "Media Types" registry at </ins> https://www.iana.org/assignments/media-types [1] with the registration information in media-types for the media types "message/ ohttp-req", "message/ohttp-res", and "application/ohttp-keys". <ins> IANA are requested to create a new entry in the "HTTP Problem Type" registry established by PROBLEM. </ins> 12.  References 12.1.  URIs


7.2.3. This document assumes that all communication between different <del> entities is protected by HTTPS.  This protects information about </del>  which resources are the subject of request and prevents a network observer from being able to trivially correlate messages on either <del> side of a relay. </del>  <del> As the time at which Encapsulated Request or response messages are sent can reveal information to a network observer.  Though messages </del>  exchanged between the Oblivious Relay Resource and the Oblivious Gateway Resource might be sent in a single connection, traffic analysis could be used to match messages that are forwarded by the This could latency to the overall time clients take to receive a response, which might not be what some clients want. <del> A relay can use padding to reduce the effectiveness of traffic analysis.  Padding is a capability provided by binary HTTP messages; see BINARY. </del> A relay that forwards large volumes of exchanges can provide better privacy by providing larger sets of messages that need to be matched.  7.3. The Oblivious Gateway Resource can be operated by a different entity

Hi, Since the gateways are seeing request/response pairs, there is a potential here for a side-channel attack at the gateway itself or at a relay. (if I understood the draft correctly - if not, please clarify my misunderstanding here). Are there mitigations planned for this type of issue that you could expand on in the Security Considerations section perhaps?
Does the new text in address this concern?
I don't think so, because the claim is the gateway does not have intimate knowledge of the contents of the request/response. If that assertion is true, the gateway shouldn't be able to ascertain information about the actual contents from those pairs (directly or indirectly, via a side-channel attack). If the burden is on the application developer to ensure that request/response pairs traversing the gateway are to be resilient to side-channel attacks of those pairings, then it would be good to explicitly call that out in this spec (perhaps in the security considerations section?) Thoughts?
NAME the gateway necessarily sees all request and response pairs, and will therefore always learn information about each transaction. This is fundamental to the design. Whether or not the gateway uses that information for malicious purposes, e.g., by providing different responses to different requests for the same target resource, depends on the trust model. And the change in addresses that. I don't think further text is needed here.
"Finally, a relay can also generate responses, though it assumed to not be able to examine the content of a request (other than to observe the choice of key identifier, KDF, and AEAD), so it is also assumed that it cannot generate an Encapsulated Response." I feel that a relay could certainly perform a side-channel attack here as well using R/R pairings.
Can you please be more specific here? What type of attack could the relay do to violate client privacy that is not already documented in the draft?
Typically in HTTPs scenarios, it is more difficult to perform side channel attacks as a flow observer, especially if multiplexing of requests and responses are performed. In this design, if I understand it correctly, the requests and responses are being broken out into distinct exchanges that the relay can see and therefore it makes it easier for a relay to perform these types of attacks that would be more difficult had the relay not been used in the first place. If my understanding of the protocol is incorrect here, please feel free to point that out.
You seem to be describing fingerprinting attacks, wherein the observer uses features extracted from otherwise encrypted traffic to try and learn information about the underlying (unencrypted) data. Yes, the relay does have a more fine-grained view of each exchange compared to a network observer in this protocol since it can see explicit message boundaries, and that might impact the efficacy of these attacks. This is partly already addressed in the document: We could extend this to note the relay's view of message boundaries. I don't think any additional text is needed for the gateway.
Whatever you feel is best. I think some language around the message level risks this creates vs non-relay scenarios might be helpful. Does the client intentionally break things up in a way that crosses the underlying application message boundaries (e.g. more like packetization) with a relay? I have more questions about the gateway functionality that we can discuss separately.
LGTM. Spelling out names in full is a pain, but probably worthwhile.

7.2.3. This document assumes that all communication between different  <ins> Oblivious Client, Oblivious Relay Resource, and Oblivious Gateway Resource is protected by HTTPS.  This protects information about </ins> which resources are the subject of request and prevents a network observer from being able to trivially correlate messages on either  <ins> side of a relay.  However, it does not mitigate traffic analysis by such network observers. </ins>  <ins> The time at which Encapsulated Request or response messages are sent can reveal information to a network observer.  Though messages </ins> exchanged between the Oblivious Relay Resource and the Oblivious Gateway Resource might be sent in a single connection, traffic analysis could be used to match messages that are forwarded by the This could latency to the overall time clients take to receive a response, which might not be what some clients want.  A relay that forwards large volumes of exchanges can provide better privacy by providing larger sets of messages that need to be matched. <ins> Traffic analysis is not restricted to network observers.  A malicious Oblivious Relay Resource could use traffic analysis to learn information about otherwise encrypted requests and responses relayed between clients and gateways.  An Oblivious Relay Resource terminates TLS connections from clients, so they see message boundaries.  This privileged position allows for richer feature extraction from encrypted data, which might improve traffic analysis. Clients can use padding to reduce the effectiveness of traffic analysis.  Padding is a capability provided by binary HTTP messages; see BINARY. </ins> 7.3. The Oblivious Gateway Resource can be operated by a different entity


by matching KeyConfig.key_id, or, if the Target Resource is willing to use trial decryption, a limited set of key configurations that share an identifier.  An Oblivious Relay Resource can link requests <del> using the public key corresponding to KeyConfig.key_id. Request resources are capable of linking requests depending on how KeyConfigs are produced by servers and discovered by clients. Specifically, servers can maliciously construct key configurations to track individual clients.  A specific method for a client to acquire key configurations is not included in this specification.  Clients need to consider these tracking vectors when choosing a discovery method.  Applications using this design should provide accommodations to mitigate tracking using key configurations.  CONSISTENCY provides an analysis of the options for ensuring the key configurations are consistent between different clients. </del>  9.

URL a partial one. From IETF 114: I don't know if it is worth enumerating all of the combinations is viable, but we might consider talking about the exact shape of the consistency requirements here.

by matching KeyConfig.key_id, or, if the Target Resource is willing to use trial decryption, a limited set of key configurations that share an identifier.  An Oblivious Relay Resource can link requests  <ins> using the public key corresponding to KeyConfig.key_id or via the URI of the Oblivious Gateway Resource.  We refer to this set of information as the gateway's configuration. Whether or not targets can link requests depends on how gateway configuration information is produced and discovered by clients. Specifically, gateways can maliciously construct configurations to track individual clients. Ideally, all clients share a consistent view of the gateway configuration.  The number of different valid configurations can exponentially partition the anonymity set of clients.  For example, if there are two valid configurations, that would yield two anonymity sets consisting of clients that used one configuration and clients that used the other configuration.  If the size of each set is large enough, this may not be a significant loss of privacy in practice. Ensuring that many clients share a configuration is necessary to provide privacy for clients. A specific method for a client to acquire configurations is not included in this specification.  Applications using this design MUST provide accommodations to mitigate tracking using gateway configurations.  CONSISTENCY provides options for ensuring that configurations are consistent between clients. </ins> 9.