Owen Kirby osk@exegin.com writes:
The Input to the CBC-MAC used in CCM mode takes the form: L(adata) | adata | padding | plaintext | padding
[...]
In other words, blen is the length of data input to the CBC-MAC modulus the block size.
[...]
Once we find the end of the adata (this is currently done on the first call to ccm_encrypt() or ccm_decrypt()), we need to insert the padding before the plaintext, which is what ccm_pad() does.
Thanks for the explanations. Might make sense to add a comment saying that when ccm_pad is called from _encrypt/_decrypt, all but the first calls are always nops.
If the context kept track of the amount of message data processed, it would be clearer to do something like if (ctx->processed_msg_data == 0) ccm_pad(), but it's not worth adding an additional counter to the context only for this purpose.
And implicit signalling end of adata by the first call to _encrypt/_decrypt (or directly to _digest, in case of an empty message) is the convention used for other aead algorithms in nettle.
Since the IV only contains a single bit that indicates whether adata exists at all, in theory the alength parameter could be omitted from set_nonce() entirely and then handled in ccm_update(), which is what this check is doing.
This is more or less an artifact of an attempt to support the AEAD API. Note that if you call ccm_set_nonce() with alength==0, and then pass the entire adata to ccm_update(), you would still get the correct authentication tag and ciphertext because of this special check on alen.
I think one should choose to either require alength to be passed to set_nonce, and drop support for the usage above. Or restrict the api to allow only a single call to ccm_update, and then drop the alength argument from set_nonce. And I think allowing multiple calls to ccm_update seems desirable, so I'd prefer the first option. Do you agree?
On Sat, Mar 15, 2014 at 12:07 AM, Niels Möller nisse@lysator.liu.se wrote:
Is it possible to move this initial processing to ccm_set_nonce? The alength *is* known there, and that would let you eliminate the ctx->blen < 0 cases, and maybe you could eliminate the alen state variable too (or keep it for sanity checking only).
Yes, that could be done, but this operation requires the use of the cipher encrypt function, which would need to be added to the set_nonce() API.
I think it's fine to have set_nonce call the encrypt function. chacha_poly1305_set_nonce does something a bit similar (but with fixed algorithms so no function pointers passed around).
And in general, nettle applications are expected to call the appropriate _set_key function *before* calling _set_nonce, so there is little point in allowing _set_nonce first for ccm.
Yes, this was a bit of a judgement call, whether it was uglier to store the nonce length in the ctx, or to parse it out of the flags byte of the counter. There are other possible ways to do this, but they all require extra storage in the ctx, which I was hoping to avoid.
I see. Your choice makes sense to me.
CCM is indeed specified as an AEAD function with a single output string, for example, RFC 5166 specifies that the ciphertext is always exactly 16 bytes longer than the plaintext, so this might be a good way to simplify the function call API.
Then the all-in-one encrypt function should have a single output, formatted accordingly. And the decrypt function should accept the same format as input.
About the tag length, do other protocols or applications use shorter tag length with ccm? The all-in-one-functions should aim to be easy to use, and they don't need to be fully general (since applications with special needs can always call the more general and lower-level functions). *If* almost all potential users of the all-in-one-functions use tag length 16, we might consider restricting the all-in-one functions to always use this size, and then drop the taglength argument.
Generally, I would prefer that the length provided should be the length of data that actually gets written (ie: ciphertext in this case).
I think that's a reasonable guideline. Then, the length arguments should be clen for ccm_encrypt_message, and mlen for ccm_decrypt_message.
I didn't see any similar functions for the EAX or CGM modes, so I'm not sure that we really need to be concerned with breaking a precedent here.
Similar all-in-one functions for other aead algorithms are on the roadmap, but not yet implemented. So when designing the interface for ccm, we should try to avoid that coming interface design for other aead algorithms have to choose between, on one hand, beauty, and on the other hand, consistency with ccm.
The negative value of blen is currently only used as a special value to flag the first time that ccm_update() gets called so that we can encrypt the IV to the CBC-MAC (B0) and generate the L(a). These operations could be moved into ccm_set_nonce(), provided that ccm_set_nonce() is also provided with the cipher encrypt function.
I think moving these operations will be an improvement.
Regards, /Niels