Hello David,

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

Attachment: smime.p7s
Description: S/MIME Cryptographic Signature



Reply via email to