I assume that 'number /nonce/' should mean the result of the concatenated parts of the IV. In case of the AES-CTR IPSec draft, you get the IV by concatenating a msg number, a nonce, and the counter (at start initialized to 0). You can then safely incerement the 128 bit IV, *unless* you overflow the counter part (the lower 32 bits of the IV, according to the AES-CTR IPSec draft).In the specification of CTR mode, as proposed for AES, you will find the statement "The number /nonce/ is incremented following each encryption." I interpreted this to mean that the top 2^64 bits are to be incremented for each successive block, and this is how I implemented the code.
Further review has indicated everyone else seems to think this means theIf you have a message number in the IV, you'd naturally incement the message number for each message (each message consisting of an arbitrary number of blocks), but then you'd also clear the counter to 0 and maybe even choose a new random nonce part. In the Schneier / Fergusson example, a 48 bit message number, a 16 bit random part and a 64 bit counter are used. When you start a new message, from my understanding you'd clear bits 0-63, and increment the msg number spanning bits 80-127. Probably, if your protocol or format allows for it, you'd also choose a new nonce (i.e. fill bits 64-79 with new random data). Since the recepient of the encryptded data can't guess the 16 bit random part if it changes, it is necessary to prepend the new IV, and accomodate for that in the message format or communication protocol. For online transmissions, it would be reasonable to start a re-keying handshake for this.
nonce is incremented only between streams and it's the counter that is
incremented between blocks;
On the matter of overflowing the lower 64 bits, this is not specificallyI'm not sure what you mean with 'the correct failure', but the clean way to handle a counter overflow would be to fail / report an error, instead of continuing to encrypt. But this is also a matter of interoperability. Since you should not wrap the counter around (as it would offer a weakness for attackers), nobody who is trying to decrypt the data would expect to allow for wrapping. On the other hand, the same function is used for decrypting and encrypting, and when decrypting, failing might be worse than continuing.
addressed in the submission (I think they assumed nobody would exceed 2^64
blocks per stream, which is reasonable) and thus I think wrapping is the
correct failure.
This discussion is academic for 64 bit counters, of course, as you probably won't see a 64 bit counter wrap very often. With a 32 bit counter however, the risk is a lot higher. Unfortunately, the current basic crypto functions offered by OpenSSL don't support returning an error condition, so 'failing' is not an option anyway.
It is debatable whether wrapping the counter would be less bad than incrementing the nonce part. A wrapping counter is more predictable for an attacker (as it would occur *always* when the communication exceeds 2**32 or 2 **64 blocks) than an unlucky nonce choice. In other words: If we let the counter wrap, the user is always affected when the counter overflows, and the weak spot is predictable. If we allow to increment the nonce instead of wrapping the counter, the user is only affected when the counter overflows, *and* he continues to reuse the same key but chooses a new nonce, *and* the choosen nonce value collides with the incremented nonce.To increment the nonce introduces a more insidious failure mode where the user unintentionally reuses nonces.
I think the intention of the boundary for the counter part is NOT to allow for wrapping, but to have a mechanism in place to ensure that a single IV (nonce + counter) is not used twice. If you just seeded the whole 128 bits with random data, and incremented them as if the counter was 128 bit, *and* you were using the same symmetric key for more than one message / transmission, you could be unlucky (most likely if your PRNG is suboptimal) and generate an IV that you've used already because of the counting. Separating the counter and the nonce leads to having a minimum distance of 32 or 64 bits between IVs, when you are careful to always use a fresh random nonce part. Implementing a mechanism to avoid collisions of IVs would be cumbersome otherwise.Other specifications have suggested that nonce be of unspecified length, not exactly 64 bits; this implies that the lower bits wrap in an overflow condition, otherwise there would be no need to specify a boundary between the different parts of counter at all.
The easiest way to go about it would be to increment the user supplied IV by 1 for each encrypted block, and leave it to the user of this function to make sure that no overflow in the counter can occur. This obligation to the programmer should be written somewhere in big letters ;-) (i.e. DON'T USE COUNTER MODE TO ENCRYPT MORE THAN 2**32 [or 2**64, depending on the counter size] BLOCKS WITH THE SAME KEY!). Higher level routines, i.e. the SSL BIO, should avoid counter overflows automatically for the user by initiating a rehandshake.Unfortunately, implementing this (as has been requested) would require more significant changes to the API than I know how to make,as passing parameters to a mode doesn't appear to be supported today.
- David
______________________________________________________________________ OpenSSL Project http://www.openssl.org Development Mailing List [EMAIL PROTECTED] Automated List Manager [EMAIL PROTECTED]