Draft: draft-thomson-http-oblivious

Commentary: 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 do n'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  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 does n'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 is n'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 , 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 .
The size of the Nonce field in an Encapsulated Response corresponds
to the size of an AEAD key for the corresponding HPKE ciphersuite.
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.
Concatenate the length of "keyID" as a variable-length integer,
"keyID", "enc" and "ct", yielding an Encapsulated Request
"enc_request".
Concatenate the length of "keyID" as a variable-length integer,
"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".
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".
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.
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".  If no such key exists, the server returns an error.
Construct additional associated data, "aad", as the Key Identifier
"keyID" from "enc_request".
Decrypt "ct" using "aad" as associated data, yielding "request" or
an error on failure.  If decryption fails, the server returns an
error.
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".
Export a secret "secret" from "context", using the string
"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".
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.
Encrypt "response", passing the AEAD function Seal the values of
"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".
Clients decrypt an Encapsulated Request by reversing this process.
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.