return FALSE;
}
+
+int smemeq(const void *av, const void *bv, size_t len)
+{
+ const unsigned char *a = (const unsigned char *)av;
+ const unsigned char *b = (const unsigned char *)bv;
+ unsigned val = 0;
+
+ while (len-- > 0) {
+ val |= *a++ ^ *b++;
+ }
+ /* Now val is 0 iff we want to return 1, and in the range
+ * 0x01..0xFF iff we want to return 0. So subtracting from 0x100
+ * will clear bit 8 iff we want to return 0, and leave it set iff
+ * we want to return 1, so then we can just shift down. */
+ return (0x100 - val) >> 8;
+}
struct tm ltime(void);
+/* Wipe sensitive data out of memory that's about to be freed. Simpler
+ * than memset because we don't need the fill char parameter; also
+ * attempts (by fiddly use of volatile) to inhibit the compiler from
+ * over-cleverly trying to optimise the memset away because it knows
+ * the variable is going out of scope. */
void smemclr(void *b, size_t len);
+/* Compare two fixed-length chunks of memory for equality, without
+ * data-dependent control flow (so an attacker with a very accurate
+ * stopwatch can't try to guess where the first mismatching byte was).
+ * Returns 0 for mismatch or 1 for equality (unlike memcmp), hinted at
+ * by the 'eq' in the name. */
+int smemeq(const void *av, const void *bv, size_t len);
+
/*
* Debugging functions.
*
{
unsigned char correct[16];
hmacmd5_genresult(handle, correct);
- return !memcmp(correct, hmac, 16);
+ return smemeq(correct, hmac, 16);
}
static void hmacmd5_do_hmac_internal(void *handle,
{
unsigned char correct[16];
hmacmd5_do_hmac_ssh(handle, blk, len, seq, correct);
- return !memcmp(correct, blk + len, 16);
+ return smemeq(correct, blk + len, 16);
}
const struct ssh_mac ssh_hmac_md5 = {
{
unsigned char correct[32];
hmacsha256_genresult(handle, correct);
- return !memcmp(correct, hmac, 32);
+ return smemeq(correct, hmac, 32);
}
static int sha256_verify(void *handle, unsigned char *blk, int len,
{
unsigned char correct[32];
sha256_do_hmac(handle, blk, len, seq, correct);
- return !memcmp(correct, blk + len, 32);
+ return smemeq(correct, blk + len, 32);
}
const struct ssh_mac ssh_hmac_sha256 = {
{
unsigned char correct[20];
hmacsha1_genresult(handle, correct);
- return !memcmp(correct, hmac, 20);
+ return smemeq(correct, hmac, 20);
}
static int sha1_verify(void *handle, unsigned char *blk, int len,
{
unsigned char correct[20];
sha1_do_hmac(handle, blk, len, seq, correct);
- return !memcmp(correct, blk + len, 20);
+ return smemeq(correct, blk + len, 20);
}
static void hmacsha1_96_genresult(void *handle, unsigned char *hmac)
{
unsigned char correct[20];
hmacsha1_genresult(handle, correct);
- return !memcmp(correct, hmac, 12);
+ return smemeq(correct, hmac, 12);
}
static int sha1_96_verify(void *handle, unsigned char *blk, int len,
{
unsigned char correct[20];
sha1_do_hmac(handle, blk, len, seq, correct);
- return !memcmp(correct, blk + len, 12);
+ return smemeq(correct, blk + len, 12);
}
void hmac_sha1_simple(void *key, int keylen, void *data, int datalen,