]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
chunk: Add predictable hash function
authorTobias Brunner <tobias@strongswan.org>
Fri, 28 Jun 2013 10:12:41 +0000 (12:12 +0200)
committerTobias Brunner <tobias@strongswan.org>
Fri, 28 Jun 2013 15:00:29 +0000 (17:00 +0200)
Since chunk_hash() is randomized its output is not predictable, that is,
it is only within the same process.

src/libstrongswan/tests/test_chunk.c
src/libstrongswan/utils/chunk.c
src/libstrongswan/utils/chunk.h

index 4f60dab8aa314670624095b91bbcfed81b26312b..7f07d057b01cb2c2c04b2f6b3f7481720e1263e6 100644 (file)
@@ -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));
index 61c7bd5a515c0926d05ab173053c5bb7d5cce887..04f3eea7dff6751068f8785af6cdb054b7ee9f18 100644 (file)
@@ -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.
  */
index b9f2bf266e27565cb3b8f84ade8c4dc34197be93..34ba773571512eb8985c934dede77b7afdfec61b 100644 (file)
@@ -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.
  *