Draft: draft-thomson-http-oblivious

Commentary: This just expands the text and tries to be explicit about everything . The one change I 've included here is a change from 32 to Nsk for the exported secret . I think that 's in line with the HPKE intent . Constants make me nervous . 
 I 'm going to merge , and then apply my suggestions and the nonce change in a followup PR . 
 In our discussion of , 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 do n'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 can not reconstruct ( unless it also counts and does trial decryption , but that 's two bad actors ) . That should ensure that the client does n'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 does n'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 do n'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 is n'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 does n't really hedge against the misuse scenario . I 'll propose text in . 
 Fixed in .
This draft includes pseudocode that uses the functions and
conventions defined in HPKE.
This draft uses the variable-length integer encoding from Section 16
of QUIC.  Encoding and decoding variable-length integers to a
sequence of bytes are described using the functions "vencode()" and
"vdecode()".  The function "len()" takes the length of a sequence of
bytes.
Formats are described using notation from Section 1.3 of QUIC.
A binary-encoded HTTP message [CITEME].
The encapsulated message Key ID, as well as the encryption mechanics,
are different for requests and responses, as described below.
Clients construct the Encapsulated Message "req" using "keyID" and
"encrypted_msg".
Servers MUST verify that the Plaintext Message padding consists of
all zeroes before processing the corresponding Message.
Extract and Expand are functions corresponding to the HPKE context's
KDF algorithm, and Seal, Nk, and Nn correspond to the HPKE context's
AEAD algorithm.
Clients decrypt an Encapsulated Message by reversing this process.
Namely, they derive the necessary AEAD parameters from an existing
HPKE context and then decrypt (open) the Encapsulated Message
encrypted message.
A binary-encoded HTTP message; see BINARY.
An Encapsulated Request is comprised of a length-prefixed key
identifier and a HPKE-protected request message.  HPKE protection
includes an encapsulated KEM shared secret (or "enc"), plus the AEAD-
protected request message.  An Encapsulated Request is shown in fig-
enc-request. request describes the process for constructing and
processing an Encapsulated Request.
Responses are bound to responses and so consist only of AEAD-
protected content.  response describes the process for constructing
and processing an Encapsulated Response.
Compute an HPKE context using "pkR", yielding "context" and
encapsulation key "enc".
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.
Encrypt (seal) "request" with "keyID" as associated data using
"context", yielding ciphertext "ct".
Concatenate the length of "keyID" as a variable-length integer,
"keyID", "enc" and "ct", yielding an Encapsulated Request
"enc_request".
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
"keyID".
Compute an HPKE context using "skR" and the encapsulated key
"enc", yielding "context".
Construct additional associated data, "aad", by prepending a
single byte with a value of 0x01 to the key identifier.
Decrypt "ct" using "aad" as associated data, yielding "request" or
an error on failure.
Servers MUST verify that the request padding consists of all zeroes
before processing the corresponding Message.
Export a secret "secret" from "context", using the string
"response" as a label.  The length of this secret is "Nsk" - the
length of the secret assocated with "context".
Extract a pseudorandom key "prk" using the "Extract" function
provided by the KDF algorithm associated with "context".  The
"ikm" input to this function is "secret"; the "salt" input is
"request".
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
the AEAD associated with "context".  Generating "key" uses a label
of "key".
Use the same "Expand" function to extract a nonce "nonce" of
length "Nn" - the length of the nonce used by the AEAD.
Generating "nonce" uses a label of "nonce".
Construct additional associated data "aad", that consists of a
single byte with a value of 0x02.
Encrypt "response", passing the AEAD function Seal the values of
"key", "nonce", "aad", and a "pt" input of "request", which yields
"enc_response".
Clients decrypt an Encapsulated Request by reversing this process.
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.