[tor-dev] memcmp() & co. timing info disclosures?

Marsh Ray marsh at extendedsubset.com
Sat May 7 05:35:26 UTC 2011


On 05/06/2011 09:40 PM, Marsh Ray wrote:
> On 05/06/2011 08:00 PM, Nick Mathewson wrote:
>
>> int mem_neq(const void *m1, const void *m2, size_t n)
>> {
>> const uint8_t *b1 = m1, *b2 = m2;
>> uint8_t diff = 0;
>> while (n--)
>> diff |= *b1++ ^ *b2++;
>> return diff != 0;
>> }
>> #define mem_eq(m1, m2, n) (!mem_neq((m1), (m2),(n)))
>
> Looks good to me.

Spoke too soon.

A little birdie (goes by the name of Skywing) pointed out to me in chat 
that certain compilers are smart enough to realize that the 
externally-visible result of the function can only go from 0 to 1 one 
time. This might enable them to break out of the loop early once that 
happened.

A workaround may be the 'volatile sledgehammer':

int mem_neq(const void *m1, const void *m2, size_t n)
{
     const uint8_t *b1 = m1, *b2 = m2;
     uint8_t diff = 0;
     volatile uint8_t * pdiff = &diff;
     while (n--)
         *pdiff |= *b1++ ^ *b2++;
     return *pdiff != 0;
}

or perhaps

int mem_neq(const void *m1, const void *m2, size_t n)
{
     const uint8_t *b1 = m1, *b2 = m2;
     uint8_t diff = 0;
     while (n--)
     {
         diff |=   *(volatile const uint8_t *)b1
                 ^ *(volatile const uint8_t *)b2;
         b1++; b2++;
     }
     return diff != 0;
}

Of course, we could always just compute SHA-256 hashes of each side and 
then compare those, right? :-)

- Marsh


More information about the tor-dev mailing list