return !m;
}
+CALLBACK(attack_memeq5, bool,
+ u_char *subj, u_char *data, size_t len)
+{
+ return memeq_const(subj, data, len);
+}
+
static bool attack_memeq(char *name, u_int iterations, u_int distance)
{
struct {
{ "memeq2", attack_memeq2 },
{ "memeq3", attack_memeq3 },
{ "memeq4", attack_memeq4 },
+ { "memeq5", attack_memeq5 },
};
u_char exp[16];
int i;
if (argc < 3)
{
fprintf(stderr, "usage: %s <attack> <iterations> <distance>\n", argv[0]);
- fprintf(stderr, " <attack>: memeq[1-4] / aead / signer\n");
+ fprintf(stderr, " <attack>: memeq[1-5] / aead / signer\n");
fprintf(stderr, " <iterations>: number of invocations * 1000\n");
fprintf(stderr, " <distance>: time difference in ns for a hit\n");
fprintf(stderr, " example: %s memeq1 100 500\n", argv[0]);
}
END_TEST
+/*******************************************************************************
+ * memeq/const
+ */
+
+static struct {
+ char *a;
+ char *b;
+ size_t n;
+ bool res;
+} memeq_data[] = {
+ {NULL, NULL, 0, TRUE},
+ {"a", "b", 0, TRUE},
+ {"", "", 1, TRUE},
+ {"abcdefgh", "abcdefgh", 8, TRUE},
+ {"a", "b", 1, FALSE},
+ {"A", "a", 1, FALSE},
+ {"\0a", "\0b", 2, FALSE},
+ {"abc", "abd", 3, FALSE},
+ {"abc", "dbd", 3, FALSE},
+ {"abcdefgh", "abcdffgh", 8, FALSE},
+ {"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz",
+ "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz", 52, TRUE},
+ {"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz",
+ "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyy", 52, FALSE},
+ {"bbcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz",
+ "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz", 52, FALSE},
+};
+
+START_TEST(test_memeq)
+{
+ ck_assert(memeq(memeq_data[_i].a, memeq_data[_i].b,
+ memeq_data[_i].n) == memeq_data[_i].res);
+}
+END_TEST
+
+START_TEST(test_memeq_const)
+{
+ ck_assert(memeq_const(memeq_data[_i].a, memeq_data[_i].b,
+ memeq_data[_i].n) == memeq_data[_i].res);
+}
+END_TEST
+
/*******************************************************************************
* memstr
*/
tcase_add_test(tc, test_memxor_aligned);
suite_add_tcase(s, tc);
+ tc = tcase_create("memeq");
+ tcase_add_loop_test(tc, test_memeq, 0, countof(memeq_data));
+ tcase_add_loop_test(tc, test_memeq_const, 0, countof(memeq_data));
+ suite_add_tcase(s, tc);
+
tc = tcase_create("memstr");
tcase_add_loop_test(tc, test_memstr, 0, countof(memstr_data));
suite_add_tcase(s, tc);
return memcmp(x, y, len) == 0;
}
+/**
+ * Same as memeq(), but with a constant runtime, safe for cryptographic use.
+ */
+bool memeq_const(const void *x, const void *y, size_t len);
+
/**
* Calling memcpy() with NULL pointers, even with n == 0, results in undefined
* behavior according to the C standard. This version is guaranteed to not