Nikos Mavrogiannopoulos nmav@redhat.com writes:
In this function, you treat empty associated data or nonce as those elements missing in the input vector to S2V. E.g., if both adata and nonce are empty, the input vector is { plaintext }, one single element. But it could also be { "", "", plaintext }, with three elements, the first two being empty strings.
While the low level function could handle it, it is not exposed to be called directly (mainly intentionally as this cipher introduces a very new paradigm which I do not quite see much of practical uses).
This patch only adds the higher level AEAD API only, so this case cannot happen as we don't have the notion of empty string in nettle. We can introduce it of course, though we may be opening a can of worms as not only empty strings are undefined in terms of AEAD API [0], but what would these mean in the other implementations?
By empty string I simply meant a string of length 0. As I read RFC 5116, it requires that the key is between 1 and 255 octets (inclusive), but all of nonce, plaintext and associated data may consist of zero octets.
To me, this sounds like a likely source of interop problems. Since RFC 5297 is general and allows the application to decide on the number of elements and meaning of the input vector, it doesn't give much guidance on this, as far as I see. The crucial case is when an application specifies that SIV is used with associated data and/or a nonce, but allows an empty string for either of those.
I agree on that. That's one of the reasons I stuck on the higher level AEAD API (expressed by the message APIs in nettle). I added two sentences in the documentation about it.
The thing is, the AEAD api should allow inputs to be zero-length strings. Then the question is how to treat zero-length inputs in _siv_s2v, and I don't find RFC 5297 crystal clear on this point.
To me, it would make most sense for the AEAD construction to always use the S2V function in the spec with S1 = associated data (possibly zero length), S2 = nonce (possibly zero length), S3 = plaintext (possibly zero length). But we need to do what's needed to make it easy to interoperate with applicatinos and protocols using SIV; if everyone else does this differently, we should probably follow.
If we do it this way, then the nonce-less "key wrapping" usecase mentioned in RFC5297, with the example in A1, is *not* a special case of the AEAD construction, since this mode uses S1 = associated data, S2 = plaintext.
If we need to support several modes, maybe we should have a context struct that lets us do S2V incrementally, one element at a time,
siv_add_adata(struct siv_ctx *ctx, size_t length, const uint8_t *data);
called zero or more times, followed by
siv_encrypt(struct siv_ctx *ctx, size_t clength, uint8_t *dst, const uint8_t *src);
which does the CMAC of the plaintext (the final S2V element), extracts V, and does the encryption. (S2V is defined also for n == 0, but that's not very useful and we don't need to support it).
But I think we should start with the AEAD-style api with both adata and nonce mandatory (but possibly empty), before worrying too much about generalizations.
Done. It needed some reorganization, and cmac128_syn is still needed in an ugly simulation of the CMAC structure setup to use the macros. I have kept the union
Maybe it would be easier without using the CMAC macros. They're intended for convenience, so there's little point in using them where it doesn't bring any convenience.
The attached version should address the comments so far and also changes cmac128_set_key to use nettle_block16 as well.
Thanks! I hope to read through the new patch during the weekend.
Regards, /Niels