This adds an stoeplitz_random_seed() function that generates a random
Toeplitz key seed with an invertible matrix T. This is necessary and
sufficient for the hash to spread out over all 65536 possible values.

While it is clear from T * (-1) == 0 that seeds with parity 0 are bad,
I don't have a neat and clean proof for the fact that a seed with
parity 1 always generates an invertible Toeplitz matrix. It's not hard
to check, but rather tedious.

I'm unsure how to hook it up. I enabled random seeds by using the
function in stoeplitz_init(), but that's just for illustration.

Index: sys/net/toeplitz.c
===================================================================
RCS file: /var/cvs/src/sys/net/toeplitz.c,v
retrieving revision 1.7
diff -u -p -r1.7 toeplitz.c
--- sys/net/toeplitz.c  19 Jun 2020 08:48:15 -0000      1.7
+++ sys/net/toeplitz.c  25 Jun 2020 18:43:02 -0000
@@ -69,9 +69,38 @@ static struct stoeplitz_cache        stoeplitz_
 const struct stoeplitz_cache *const
                                stoeplitz_cache = &stoeplitz_syskey_cache; 
 
+/* parity of n16: count (mod 2) of ones in the binary representation. */
+int
+parity(uint16_t n16)
+{
+       n16 = ((n16 & 0xaaaa) >> 1) ^ (n16 & 0x5555);
+       n16 = ((n16 & 0xcccc) >> 2) ^ (n16 & 0x3333);
+       n16 = ((n16 & 0xf0f0) >> 4) ^ (n16 & 0x0f0f);
+       n16 = ((n16 & 0xff00) >> 8) ^ (n16 & 0x00ff);
+
+       return (n16);
+}
+
+/*
+ * The Toeplitz matrix obtained from a seed is invertible if and only if the
+ * parity of the seed is 1. Generate such a seed uniformly at random.
+ */
+stoeplitz_key
+stoeplitz_random_seed(void)
+{
+       stoeplitz_key seed;
+       
+       seed = arc4random() & UINT16_MAX;
+       if (parity(seed) == 0)
+               seed ^= 1;
+
+       return (seed);
+}
+
 void
 stoeplitz_init(void)
 {
+       stoeplitz_keyseed = stoeplitz_random_seed();
        stoeplitz_cache_init(&stoeplitz_syskey_cache, stoeplitz_keyseed);
 }
 

Reply via email to