From: Tobias Brunner Date: Fri, 28 Jun 2013 10:12:41 +0000 (+0200) Subject: chunk: Add predictable hash function X-Git-Tag: 5.1.0dr1~18 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ed235dbbf26cbeaf0a57173eb6f1c9a196ab4a6d;p=thirdparty%2Fstrongswan.git chunk: Add predictable hash function Since chunk_hash() is randomized its output is not predictable, that is, it is only within the same process. --- diff --git a/src/libstrongswan/tests/test_chunk.c b/src/libstrongswan/tests/test_chunk.c index 4f60dab8aa..7f07d057b0 100644 --- a/src/libstrongswan/tests/test_chunk.c +++ b/src/libstrongswan/tests/test_chunk.c @@ -698,7 +698,6 @@ START_TEST(test_chunk_mac) } END_TEST - /******************************************************************************* * test for chunk_hash[_inc]() */ @@ -721,6 +720,35 @@ START_TEST(test_chunk_hash) } END_TEST +/******************************************************************************* + * test for chunk_hash_static[_inc]() + */ + +START_TEST(test_chunk_hash_static) +{ + chunk_t in; + u_int32_t out, hash_a, hash_b, hash_inc = 0x7b891a95; + int i, count; + + count = countof(sip_vectors); + in = chunk_alloca(count); + + for (i = 0; i < count; ++i) + { + in.ptr[i] = i; + in.len = i; + /* compared to chunk_mac() we only get half the value back */ + out = chunk_hash_static(in); + fail_unless(memeq(&out, sip_vectors[i], 4), + "test vector failed for %d bytes", i); + } + hash_a = chunk_hash_static_inc(in, out); + ck_assert_int_eq(hash_a, hash_inc); + hash_b = chunk_hash_static_inc(in, out); + ck_assert_int_eq(hash_a, hash_b); +} +END_TEST + /******************************************************************************* * printf_hook tests */ @@ -822,6 +850,10 @@ Suite *chunk_suite_create() tcase_add_test(tc, test_chunk_hash); suite_add_tcase(s, tc); + tc = tcase_create("chunk_hash_static"); + tcase_add_test(tc, test_chunk_hash_static); + suite_add_tcase(s, tc); + tc = tcase_create("printf_hook"); tcase_add_loop_test(tc, test_printf_hook_hash, 0, countof(printf_hook_data)); tcase_add_loop_test(tc, test_printf_hook, 0, countof(printf_hook_data)); diff --git a/src/libstrongswan/utils/chunk.c b/src/libstrongswan/utils/chunk.c index 61c7bd5a51..04f3eea7df 100644 --- a/src/libstrongswan/utils/chunk.c +++ b/src/libstrongswan/utils/chunk.c @@ -705,6 +705,12 @@ u_int64_t chunk_mac(chunk_t chunk, u_char *key) */ static u_char key[16]; +/** + * Static key used in case predictable hash values are required. + */ +static u_char static_key[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f}; + /** * Only allocate the key once */ @@ -764,6 +770,22 @@ u_int32_t chunk_hash(chunk_t chunk) return chunk_mac(chunk, key); } +/** + * Described in header. + */ +u_int32_t chunk_hash_static_inc(chunk_t chunk, u_int32_t hash) +{ /* we could use a mac of the previous hash, but this is faster */ + return chunk_mac_inc(chunk, static_key, ((u_int64_t)hash) << 32 | hash); +} + +/** + * Described in header. + */ +u_int32_t chunk_hash_static(chunk_t chunk) +{ + return chunk_mac(chunk, static_key); +} + /** * Described in header. */ diff --git a/src/libstrongswan/utils/chunk.h b/src/libstrongswan/utils/chunk.h index b9f2bf266e..34ba773571 100644 --- a/src/libstrongswan/utils/chunk.h +++ b/src/libstrongswan/utils/chunk.h @@ -302,7 +302,13 @@ bool chunk_printable(chunk_t chunk, chunk_t *sane, char replace); /** * Computes a 32 bit hash of the given chunk. * - * @note This hash is only intended for hash tables not for cryptographic purposes. + * @note The output of this function is randomized, that is, it will only + * produce the same output for the same input when calling it from the same + * process. For a more predictable hash function use chunk_hash_static() + * instead. + * + * @note This hash is only intended for hash tables not for cryptographic + * purposes. * * @param chunk data to hash * @return hash value @@ -318,6 +324,30 @@ u_int32_t chunk_hash(chunk_t chunk); */ u_int32_t chunk_hash_inc(chunk_t chunk, u_int32_t hash); +/** + * Computes a 32 bit hash of the given chunk. + * + * Compared to chunk_hash() this will always calculate the same output for the + * same input. Therefore, it should not be used for hash tables (to prevent + * hash flooding). + * + * @note This hash is not intended for cryptographic purposes. + * + * @param chunk data to hash + * @return hash value + */ +u_int32_t chunk_hash_static(chunk_t chunk); + +/** + * Incremental version of chunk_hash_static(). Use this to hash two or more + * chunks in a predictable way. + * + * @param chunk data to hash + * @param hash previous hash value + * @return hash value + */ +u_int32_t chunk_hash_static_inc(chunk_t chunk, u_int32_t hash); + /** * Computes a quick MAC from the given chunk and key using SipHash. *