Folks, Did a scan through a fair bit of our code. mod_digest is not the only place; e.g. in basic auth; we are also not as careful in all cases as we could be.
So I think that what is needed are two (or three) functions - A fairly mundane (binary) timing safe compare that compares two fixed lengths (e.g. SHA or MD5) strings or binary buffers. - A string comparison function; where at least one string is is under control of the attacker. As to the first - I think it can be as simple as below - as to the latter - see next email. As with that one I am struggling. Dw /* Oroginal code for ap_timingsafe_memcmp: libressl-portable under below license. * * Copyright (c) 2014 Google Inc. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all cop1es. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /** * Compare two binary buffers (of identical length) in a timing safe * manner. As to avoid leaking information about that what is compared * and thus preventing side channel leaks when for example comparing * a checksum or a password. *. * Both buffers are assumed to have idenitcal length. * * @param buf1 Buffer 1 to compare buffer 2 to. * @param buf2 Buffer 2 * @param len The length of the two buffers. * @return 0 when identical, non zero when different. */ AP_DECLARE(int) ap_timingsafe_memcmp(const void *b1, const void *b2, size_t len) { const unsigned char *p1 = b1, *p2 = b2; size_t i; int res = 0, done = 0; for (i = 0; i < len; i++) { /* lt is -1 if p1[i] < p2[i]; else 0. */ int lt = (p1[i] - p2[i]) >> CHAR_BIT; /* gt is -1 if p1[i] > p2[i]; else 0. */ int gt = (p2[i] - p1[i]) >> CHAR_BIT; /* cmp is 1 if p1[i] > p2[i]; -1 if p1[i] < p2[i]; else 0. */ int cmp = lt - gt; /* set res = cmp if !done. */ res |= cmp & ~done; /* set done if p1[i] != p2[i]. */ done |= lt | gt; } return (res); }