> On 26 May 2015, at 17:22, Dirk-Willem van Gulik <di...@webweaving.org> wrote:
..
> So I think that what is needed are two (or three) functions
...
> -     A string comparison function; where at least one string is is under 
> control of the attacker.

Now the issue here is that length is every easily revealed. So I can think of 2 
strategies;

-       firmly declare (in the signature of the compare function) one argument 
as potentially hostile.

        And do the comparison largely based on that; which means we only 
marginally reveal the
        actual length of the string compared to. Below is an example; but my 
gut feel it is not
        nearly good enough when you can apply a large chunk of statistics 
against it.

-       treat them both as hostile; and scan for either the shortest or longest 
one and accept
        that you leak something about length.

        Or - if needed - pad this out for strings <1024 (or similar) chars in 
length by doing always
        that many (which will leak less).

Examples are below. Suggestions appreciated. 

Dw.

static int or_bits(int  x) {
  x |= (x >> 4);
  x |= (x >> 2);
  x |= (x >> 1);
  return -(x & 1);
}

/* Quick mickey mouse version to compare the strings. XXX fixme. 
 */
AP_DECLARE(int) ap_timingsafe_strcmp(const char * hostile_string, const char * 
to_protect__string) {
        const unsigned char *p1 = (const unsigned char *)hostile_string;
        const unsigned char *p2 = (const unsigned char *)to_protect__string;
        size_t i = 0, i1 = 0 ,i2 = 0;
        unsigned int res = 0;
        unsigned int d1, d2;

        do {
                res |= or_bits(p1[i1] - p2[i2]);

                d1 = -or_bits(p1[i1]);
                d2 = -or_bits(p2[i2]);

                i1 += d1;
                i2 += d2;
                i += (d1 | d2);

#icase A
        } while (d1 | d2); // longest one will abort
#case B
        } while (d1 & d2); // shortest one will abort
#case C
        } while (i < 1024) } while (d1 | d2); // at least 1024 or longest 
one/shortest one

        // include the length in the coparision; as to avoid foo v.s. foofoofoo 
to match.
        //
        return (int) (res | ( i1 - i2));
}

Reply via email to