Appreciate the back and forth here a lot. I think we’re getting some where...
On Jun 3, 2023, at 1:56 PM, Ilari Liusvaara <[email protected]<mailto:[email protected]>> wrote: On Sat, Jun 03, 2023 at 07:56:59PM +0000, lgl island-resort.com<http://island-resort.com/> wrote: On Jun 2, 2023, at 1:52 PM, Ilari Liusvaara <[email protected]<mailto:[email protected]>> wrote: On Fri, Jun 02, 2023 at 05:59:30PM +0000, lgl island-resort.com<http://island-resort.com> wrote: Algorithm ID Binds the output key material of the HKDF to the algorithm that key material will be used with. The purpose is explained fairly well in RFC 9053. HPKE takes care of this internally for COSE-HPKE single recipient mode, but not for multiple recipient mode. AFAIK, the native ECDH mode in COSE has the same limitation: The COSE_KDF_Context binds the next algorithm. If there is only a single recipient, it is the final bulk encryption, so everything is bound. However, in case of multi-recipient, it is key wrap, leaving the final bulk encryption unbound. - COSE-HPKE single recipient — not applicable because content encryption is internal to HPKE - COSE-HPKE multiple-recipient — applicable because the next stage after HPKE is the content encryption AEAD - RFC 9053 6.1.2. Direct Key with KDF — applicable because the next stage after HPKE is the content encryption AEAD - RFC 9053 6.3.1. Direct ECDH — applicable because the next stage after HPKE is the content encryption AEAD - RFC 9053 6.4.1. ECDH with Key Wrap — not applicable because the next stage is key wrap So this mechanism can work for COSE-HPKE, but rather unfortunately not for ECDH with Key Wrap. Just because it doesn’t work for ECDH with Key Wrap doesn’t mean we shouldn’t do it for COSE-HPKE. It seems possible to design new AES Key Wrap that is an AEAD. It would have an “info” input like SealBase and HKDF. I actually was thingking how to do this. The way I came up with involved a new header parameter (nalg for "next algorithm"). and modified versions of aes-gcm and chacha-poly (the stock ones are problematic for key wrap). The nalg would match alg next layer down, and the modified versions would be for the middle layer in three-layer ECDH. Sender/Receiver Info (e.g. Party U) Appendix B of NIST SP800-56A gives the rationale referencing some papers describing attacks. This is fairly esoteric for me so far so I can't give a plain explanation. I’m still kind of looking for good guidance on how / when to use this. It seems like this is defense-in-depth rather than essential unless your use case is poorly constructed in some way. However, I think the bottom line is that is best practice nowadays, so for example COSE libraries should really support it. I see two reasons for including the info in the appendix. - The first does not look applicable, because HPKE always generates fresh keys. You are talking about every key except the static key for the recipient (pkR), right? I would expect most non-HPKE COSE implementations to do the same. Can one categorically say that if all keys are fresh (except pkR), PartyU/PartyV is completely unnecessary? The first stated reason was the same key material getting reused, and generating fresh sender key each time obviously eliminates that. The second reason contained additional reasons that might still be applicable, however those look highly application-dependent. Perhaps restating the obvious… If the ephemeral key is generated new for every message, then PartyU/V are not really needed to ensure uniqueness of the key output from the KEM (ECDH + HKDF). Another thing you could do is have the receiver compare the PartyU/V values with what is expected. For example, if my name is Joseph and I known from larger context that a message is from Jane, I then check that PartyU/V are Joseph and Jane. But maybe not, because if I’m forging encrypted messages, I can pick those to be what ever I want. Seems to me that PartyU/V should just default to strings like “sender” and “receiver” for most use cases. There can be an override for use cases that perhaps want more and/or don’t generate a new ephemeral key for every message. - The second does look applicable. However, adding it in a way that is neither trivially broken nor highly application-specific seems almost impossible. From a COSE library view, this seems fairly simple. Just allow the caller to set PartyU and PartyV. If a use case wants to go to a ton of trouble for some application-specific issue they can. If not, they default to “sender” and “receiver”. Seems like there has to be some value as they are not optional. COSE-HPKE already allows info to be set by application in case it wants to do something nontrivial with stuff like identities. So far COSE-HPKE doesn’t say anything one way or another about info being a user level parameter. My assumption, like Chris Woods, is that SealBase and HPKE are internal to a COSE library and that it wouldn’t be available in the public API. The ECDH in 9053 does require parts of COSE_KDF_Context to be input from the public API. (PartyU/V and probably “other” and “SuppPrivInfo”. I would like my COSE API to be the same for the 9053 ECDH COSE_Recipients as it is for HPKE, so I don’t want to expose the SealBase info parameter, but rather expose construction of COSE_KDF_Context in the API. However, in light of sketching JOSE-HPKE, maybe defaulting to empty string is not the best, and one should instead default to "iCOSE-HPKE" or something similar (for protocol context separation). SuppPubInfo.protected This is the super-important part that protects the protected COSE header parameters. Absolutely not optional. Because HPKE is AEAD-capable, COSE header parameters are already protected by Enc_structure (by RFC9052). Including those into KDF context would lead to double protection, which is silly. My proposal is to fully replace the Enc_structure with COSE_KDF_Context in COSE-HPKE. I am not proposing double protection. I do not think that is possible because of requirements of RFC 9052. Enc_structure of type “Enc_Recipient” seems either derelict or moribund to me. It is only discussed very briefly in 9052 section 5.3, the title of this section is "How to Encrypt and Decrypt for AEAD Algorithms”. The title implies the Enc_structure goes into the AAD input of an AEAD. No COSE_Recipient type defined so far uses AEAD or has an AAD input. RFC 9052 section 8 could have also been a place where a procedure for use of Enc_structure of type “Enc_Recipient” could have be given or a requirement set, but it is silent. I don’t know if this is intentional or just because it wasn’t thought through. Either way, there’s no requirement one way or another in 9052 that I can see. Jim’s code parallels this situation. It constructs a Enc_structure of type “Enc_Recipient” and never uses it. What we do have in COSE_Recipients is the use of an HKDF which has an “info” input. In multiple-recipient COSE-HPKE we also have an “info” input that does pretty much the same thing. Single-recipient COSE-HPKE is an odd duck that doesn’t realy follow along with COSE. Not saying it should not be done, just that we can’t expect it to fit in or use it much in the argument one way or another. I believe use of COSE_KDF_Context with COSE-HPKE is in line with COSE in general and is best practice from SP800-56A (and with JOSE). Using COSE_KDF_Context as-is with COSE-HPKE is impossible because of the keyDataLength problem. Seems fine for multiple-recipient COSE-HPKE where the next algorithm is the bulk content encryption algorithm. Seems like it would have to be no-alg / 0 for single recipient. And there is also major difference in going against RFC9052 versus going against RFC9053. With RFC9052, There is expectation that things apply, so any deviation should be very carefully considered and very explicitly called out. RFC9053 is collection of other things and it is fine to do whatever except try to redefine it (alignment is just nice to have). Agree with this assessment of 9052 vs 9053, but don’t think 9052 sets a requirement on the use of Enc_structure of type “Enc_Recipient”. Other — Hash of ciphertext Hannes has proposed that a hash of the SUIT_Digest be included here. In practice I think this is a hash of ciphertext in the COSE_Encrypt. That seems like it would be impossible to implement because of hard cyclic dependency? It is possible. We have a prototype, but I don’t think it is a good idea. In ECDH, it is probably possible, have not looked at it. However, I don't think it is possible in HPKE. Even if using multishot interface, you would need to know the hash of ciphertext before calling SetupBaseS(), but you only get the ciphertext after calling SetupBaseS(). -> Deadlock. Yes. Appreciate that as a reason not to do it. :-) LL
_______________________________________________ COSE mailing list [email protected] https://www.ietf.org/mailman/listinfo/cose
