diff options
-rw-r--r-- | scripts/timeattack.c | 48 | ||||
-rw-r--r-- | src/libstrongswan/tests/suites/test_chunk.c | 27 | ||||
-rw-r--r-- | src/libstrongswan/utils/chunk.h | 13 |
3 files changed, 87 insertions, 1 deletions
diff --git a/scripts/timeattack.c b/scripts/timeattack.c index 3d7ffee7d..ef00e8c4e 100644 --- a/scripts/timeattack.c +++ b/scripts/timeattack.c @@ -235,6 +235,48 @@ static bool attack_memeq(char *name, u_int iterations, u_int distance) 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, aead_t *aead, u_char *data, size_t len) { @@ -357,7 +399,7 @@ int main(int argc, char *argv[]) if (argc < 3) { 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, " <distance>: time difference in ns for a hit\n"); 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])); } + 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])); } diff --git a/src/libstrongswan/tests/suites/test_chunk.c b/src/libstrongswan/tests/suites/test_chunk.c index b5d23658d..312a187ac 100644 --- a/src/libstrongswan/tests/suites/test_chunk.c +++ b/src/libstrongswan/tests/suites/test_chunk.c @@ -61,6 +61,32 @@ START_TEST(test_chunk_equals) 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 */ @@ -1013,6 +1039,7 @@ Suite *chunk_suite_create() tc = tcase_create("equals"); tcase_add_test(tc, test_chunk_equals); + tcase_add_test(tc, test_chunk_equals_const); suite_add_tcase(s, tc); tc = tcase_create("chunk_compare"); diff --git a/src/libstrongswan/utils/chunk.h b/src/libstrongswan/utils/chunk.h index 48405b77e..2ec7f7543 100644 --- a/src/libstrongswan/utils/chunk.h +++ b/src/libstrongswan/utils/chunk.h @@ -310,6 +310,19 @@ static inline bool chunk_equals(chunk_t a, chunk_t b) } /** + * 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), * NULL chunks are never equal. */ |