utils: Add a constant time chunk_equals() variant for cryptographic purposes
This commit is contained in:
+47
-1
@@ -235,6 +235,48 @@ static bool attack_memeq(char *name, u_int iterations, u_int distance)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CALLBACK(attack_chunk1, bool,
|
||||||
|
u_char *subj, u_char *data, size_t len)
|
||||||
|
{
|
||||||
|
return chunk_equals(chunk_create(subj, len), chunk_create(data, len));
|
||||||
|
}
|
||||||
|
|
||||||
|
CALLBACK(attack_chunk2, bool,
|
||||||
|
u_char *subj, u_char *data, size_t len)
|
||||||
|
{
|
||||||
|
return chunk_equals_const(chunk_create(subj, len), chunk_create(data, len));
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool attack_chunk(char *name, u_int iterations, u_int distance)
|
||||||
|
{
|
||||||
|
struct {
|
||||||
|
char *name;
|
||||||
|
attackfn_t fn;
|
||||||
|
} attacks[] = {
|
||||||
|
{ "chunk1", attack_chunk1 },
|
||||||
|
{ "chunk2", attack_chunk2 },
|
||||||
|
};
|
||||||
|
u_char exp[16];
|
||||||
|
int i;
|
||||||
|
|
||||||
|
srandom(time(NULL));
|
||||||
|
for (i = 0; i < sizeof(exp); i++)
|
||||||
|
{
|
||||||
|
exp[i] = random();
|
||||||
|
}
|
||||||
|
fprintf(stderr, "attacking %b\n", exp, sizeof(exp));
|
||||||
|
|
||||||
|
for (i = 0; i < countof(attacks); i++)
|
||||||
|
{
|
||||||
|
if (streq(name, attacks[i].name))
|
||||||
|
{
|
||||||
|
return timeattack(attacks[i].fn, exp, sizeof(exp),
|
||||||
|
iterations, distance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
CALLBACK(attack_aead, bool,
|
CALLBACK(attack_aead, bool,
|
||||||
aead_t *aead, u_char *data, size_t len)
|
aead_t *aead, u_char *data, size_t len)
|
||||||
{
|
{
|
||||||
@@ -357,7 +399,7 @@ int main(int argc, char *argv[])
|
|||||||
if (argc < 3)
|
if (argc < 3)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "usage: %s <attack> <iterations> <distance>\n", argv[0]);
|
fprintf(stderr, "usage: %s <attack> <iterations> <distance>\n", argv[0]);
|
||||||
fprintf(stderr, " <attack>: memeq[1-5] / aead / signer\n");
|
fprintf(stderr, " <attack>: memeq[1-5] / chunk[1-2] / aead / signer\n");
|
||||||
fprintf(stderr, " <iterations>: number of invocations * 1000\n");
|
fprintf(stderr, " <iterations>: number of invocations * 1000\n");
|
||||||
fprintf(stderr, " <distance>: time difference in ns for a hit\n");
|
fprintf(stderr, " <distance>: time difference in ns for a hit\n");
|
||||||
fprintf(stderr, " example: %s memeq1 100 500\n", argv[0]);
|
fprintf(stderr, " example: %s memeq1 100 500\n", argv[0]);
|
||||||
@@ -368,5 +410,9 @@ int main(int argc, char *argv[])
|
|||||||
{
|
{
|
||||||
return !attack_memeq(argv[1], atoi(argv[2]), atoi(argv[3]));
|
return !attack_memeq(argv[1], atoi(argv[2]), atoi(argv[3]));
|
||||||
}
|
}
|
||||||
|
if (strpfx(argv[1], "chunk"))
|
||||||
|
{
|
||||||
|
return !attack_chunk(argv[1], atoi(argv[2]), atoi(argv[3]));
|
||||||
|
}
|
||||||
return !attack_transform(argv[1], atoi(argv[2]), atoi(argv[3]));
|
return !attack_transform(argv[1], atoi(argv[2]), atoi(argv[3]));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,6 +60,32 @@ START_TEST(test_chunk_equals)
|
|||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* equals_const
|
||||||
|
*/
|
||||||
|
|
||||||
|
START_TEST(test_chunk_equals_const)
|
||||||
|
{
|
||||||
|
chunk_t chunk = chunk_from_str("chunk");
|
||||||
|
chunk_t chunk_a, chunk_b;
|
||||||
|
|
||||||
|
chunk_a = chunk_empty;
|
||||||
|
chunk_b = chunk_empty;
|
||||||
|
ck_assert(!chunk_equals_const(chunk_a, chunk_b));
|
||||||
|
|
||||||
|
chunk_a = chunk;
|
||||||
|
ck_assert(!chunk_equals_const(chunk_a, chunk_b));
|
||||||
|
chunk_b = chunk;
|
||||||
|
ck_assert(chunk_equals_const(chunk_a, chunk_b));
|
||||||
|
|
||||||
|
chunk_b = chunk_from_str("asdf");
|
||||||
|
ck_assert(!chunk_equals_const(chunk_a, chunk_b));
|
||||||
|
|
||||||
|
chunk_b = chunk_from_str("chunk");
|
||||||
|
ck_assert(chunk_equals_const(chunk_a, chunk_b));
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* chunk_compare test
|
* chunk_compare test
|
||||||
*/
|
*/
|
||||||
@@ -1013,6 +1039,7 @@ Suite *chunk_suite_create()
|
|||||||
|
|
||||||
tc = tcase_create("equals");
|
tc = tcase_create("equals");
|
||||||
tcase_add_test(tc, test_chunk_equals);
|
tcase_add_test(tc, test_chunk_equals);
|
||||||
|
tcase_add_test(tc, test_chunk_equals_const);
|
||||||
suite_add_tcase(s, tc);
|
suite_add_tcase(s, tc);
|
||||||
|
|
||||||
tc = tcase_create("chunk_compare");
|
tc = tcase_create("chunk_compare");
|
||||||
|
|||||||
@@ -309,6 +309,19 @@ static inline bool chunk_equals(chunk_t a, chunk_t b)
|
|||||||
a.len == b.len && memeq(a.ptr, b.ptr, a.len);
|
a.len == b.len && memeq(a.ptr, b.ptr, a.len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compare two chunks for equality, constant time for cryptographic purposes.
|
||||||
|
*
|
||||||
|
* Note that this function is constant time only for chunks with the same
|
||||||
|
* length, i.e. it does not protect against guessing the length of one of the
|
||||||
|
* chunks.
|
||||||
|
*/
|
||||||
|
static inline bool chunk_equals_const(chunk_t a, chunk_t b)
|
||||||
|
{
|
||||||
|
return a.ptr != NULL && b.ptr != NULL &&
|
||||||
|
a.len == b.len && memeq_const(a.ptr, b.ptr, a.len);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compare two chunks (given as pointers) for equality (useful as callback),
|
* Compare two chunks (given as pointers) for equality (useful as callback),
|
||||||
* NULL chunks are never equal.
|
* NULL chunks are never equal.
|
||||||
|
|||||||
Reference in New Issue
Block a user