David Maurus wrote:
Goetz Babin-Ebell wrote:
The application specifies 4 datas: 1. a step size 2. a bit mask. 3. a (optional) pointer to a function that is called if the step bits that are not in the bit mask: 4. a (optional) pointer to a function doing the counting;
> if (pCounter->Range) > return pCounter->Range(pCounter); > else > return Range_restart(pCounter);
The quoted code would restart counting when the counter overflows. That would open up a predictable opportunity for attack. I am still convinced that the default behaviour should be to report an error, and if this is not possible, increment over the bit-bound of the counter (increment the nonce), as this would cause the least damage.
OK. The code was an example. We can replace Range_Retsart() with Range_Terminate()...
The idea to have a function pointer for the increment function has the advantage that one could implement a counter function that would actually not count incrementally, but otherwise unique, as alluded to in the NIST recommendation (also page 19):
"This recommendation permits the use of any other incrementing function that generates n unique
strings of m bits in succession from the allowable initial strings. For example, if the initial string
of m bits is not the "zero" string, i.e., if it contains at least one '1' bit, then an incrementing
function can be constructed from a linear feedback shift register that is specialized to ensure a
sufficiently large period; see Ref. [5] for information about linear feedback shift registers."
But then, a mask based range check would not be sufficient, since you can't rely on any overflows.
Then we could let the Count() function handle the counter range detection and return a third state: [...] int (*Count)(CounterData *pCounter); /* optional: handle a step, returns: < 0: error returns: ==0: call Range returns: > 0: OK. */ [...]
Now the Do_Counter() would change to: int Do_Counter(CounterData *pCounter) { int nRet; if (!pCounter) return -1; if (pCounter->Count) nRet = pCounter->Count(pCounter); else nRet = Count(pCounter); if (nRet != 0) return nRet; if (pCounter->Range) return pCounter->Range(pCounter); else return Range_terminate(pCounter); return nRet; }
In general, I'd prefer a more simple approach, like taking the counter bits as a parameter, and returning an int code ERR_LIB_NONE (?) if everything's OK, and an something like ERR_AES_CTR_OVERFLOW when the counter overflows...
If we change the Count() function ro return ERR_LIB_NONE on OK, ERR_CTR_OVERFLOW on counter overflow and any other error code to terminate, Do_Counter would become:
int Do_Counter(CounterData *pCounter) { int nRet; if (!pCounter) return -1; if (pCounter->Count) nRet = pCounter->Count(pCounter); else nRet = Count(pCounter); if (nRet == ERR_CTR_OVERFLOW) { if (pCounter->Range) return pCounter->Range(pCounter); else return Range_terminate(pCounter); } return nRet; }
Bye
Goetz
-- Goetz Babin-Ebell, TC TrustCenter AG, http://www.trustcenter.de Sonninstr. 24-28, 20097 Hamburg, Germany Tel.: +49-(0)40 80 80 26 -0, Fax: +49-(0)40 80 80 26 -126
smime.p7s
Description: S/MIME Cryptographic Signature