On 14-04-13 12:51 AM, Niels Möller wrote:
Owen Kirby osk@exegin.com writes:
Here's a first stab at assembling some documentation about CCM mode and its API.
Thanks! You are aware that the manual is licensed as public domain, is that ok with you?
That is ok with me.
Some minor nits that I noticed about the API while writing it:
- ccm_decrypt_message uses const void * for the cipher context, but all the other interfaces use void * for this.
Can you be more specific? I think it should be const void * everywhere, and I see no void * in the version of ccm.h which is in the repo. That's one of the things I changed when integrating it.
Ah, you are right. The I must have copy-pasted the non-const versions from the GCM section of the docs, which hasn't been updated yet to agree with the const void* used in the source. I'll make sure to change them back to const void*
- passing the clength rather mlength to ccm_decrypt_message could be a little confusing when compared to the rest of the API. In retrospect, I think Neils's initial suggestion on this API was probably the better way to go.
If I remember correctly, we agreed that when we pass the triple (length, dst, src), and the src and destination areas are of diferent sizes, then it's best to adopt the convention that length always is the size of the destination area?
Which then means that ccm_encrypt_message should take clength (length of ciphertext) and ccm_decrypt_message should be changed to take mlength (length of cleartext).
Noted, I'll make an update accordingly.
+The inputs to @acronym{CCM} are: +@itemize +@item +A key, which can be used for many messages. +@item +A parameter @var{L} which determines the size of the nonce and the maximum +length of message data which can be processed by @acronym{CCM}. +@item +A tag length, which must be a multiple of 4 bytes up to a maximum of one block. +@item +A nonce which @emph{must} be unique for each message. +@item +Optional authenticated data, which is to be included in the message +authentication, but not encrypted. +@item +The plaintext. May be empty. +@end itemize
+The outputs from @acronym{CCM} are: +@itemize +@item +The ciphertext of the same length as the plaintext. +@item +An encrypted authentication tag, up to one block on length. +@end itemize
+The parameter @var{L} determines the size of the counter that is used for the +message length, such that the maximum message length in bytes is given by +@code{maxlength = (1 << L) - 1}. However increasing @var{L} also restricts the +size of the nonce such that @code{noncelength = CCM_BLOCK_SIZE - 1 - L}, and +throughout this interface the parameter @var{L} is provided implicitly by the +nonce length.
I think it would be good with a bit more focus on how the caller should select the nonce size. I'd expect that 12 bytes nonce (and the corresponding limit on message size) is the most widely used, following RFC 5116.
What happens if the caller specifies an invalid combination of nonce size and message size? Will it trigger some assert, or will the counter wrap around silently?
The last line in ccm_build_iv will assert if the counter rolls over when forming the IV. There are no checks for rollovers when incrementing the CTR, but to do that one would have to encrypt more than (1 << (L*8)) blocks of data, and at least 16 times the amount of data that was specified in the callto ccm_set_nonce
It also occurs to me that the my formula for calculating the maximum message size from L is completely wrong. L basically specifies the size of the counter field (in bytes), so it should really be maxlength = (1 << (L*8)) - 1.
Most protocols focus on maximizing the length of the nonce, since messages seldomly exceed a few kilobytes and you want to get as much entropy into the IV as possible. Off the top of my head, I think most IETF protocols use a nonce of 12 bytes while the IEEE 802.15.4 and ZigBee use a nonce of 13 bytes. I'll try to put together a few official-sounding words on the topic.
Cheers, Owen