Subject: Re: kernel ip_randomid() and libc randomid(3) still "broken"
To: Jun-ichiro itojun Hagino <itojun@itojun.org>
From: Charles M. Hannum <abuse@spamalicious.com>
List: tech-net
Date: 11/27/2003 00:01:47
--Boundary-00=_r7Tx/CZlykTZweJ
Content-Type: text/plain;
  charset="iso-8859-1"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

BTW, regarding speed, I found that the "t" values for the pmod() call in 
ip_randomid() can be precalculated in ip_initid(), thus removing half of the 
multiple and modulus operations in the critical path.  In addition, 
hard-coding the denominator in this case allows the compiler to convert a 
complex non-constant modulus operation into a multiply-subtract on some 
platforms.  See the attached patch (which is hand-edited, so may not apply 
cleanly).

--Boundary-00=_r7Tx/CZlykTZweJ
Content-Type: text/x-diff;
  charset="iso-8859-1";
  name="id-diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
	filename="id-diff"

--- a.c	2003-11-26 22:35:21.000000000 +0000
+++ c.c	2003-11-26 23:56:30.000000000 +0000
@@ -83,7 +83,7 @@
 static u_int16_t ru_x;
 static u_int16_t ru_seed;
 static u_int16_t ru_a, ru_b;
-static u_int16_t ru_g;
+static u_int16_t ru_g, ru_t[16];
 static u_int16_t ru_counter = 0;
 static u_int16_t ru_msb = 0;
 #if 0
@@ -117,6 +117,23 @@
 	return (s);
 }
 
+static u_int16_t
+pmod2(u_int16_t t[], u_int16_t expo)
+{
+	int n;
+	u_int16_t s, u;
+
+	s = 1;
+	u = expo;
+
+	for (n = 0; u; n++) {
+		if (u & 1)
+			s = (s * t[n]) % RU_N;
+		u >>= 1;
+	}
+	return (s);
+}
+
 /*
  * Initalizes the seed and chooses a suitable generator. Also toggles
  * the msb flag. The msb flag is used to generate two distinct
@@ -128,7 +154,8 @@
 static void
 ip_initid(void)
 {
-	u_int16_t j, i;
+	u_int16_t j, i, t;
+	int n;
 	int noprime = 1;
 
 	ru_x = ((tmp = arc4random()) & 0xFFFF) % RU_M;
@@ -163,6 +190,11 @@
 	}
 
 	ru_g = pmod(RU_GEN, j, RU_N);
+	t = ru_g;
+	for (n = 0; n < 16; n++) {
+		ru_t[n] = t;
+		t = (t * t) % RU_N;
+	}
 	ru_counter = 0;
 
 #if 0
@@ -183,7 +214,7 @@
 
 	ru_counter += i;
 
-	return (ru_seed ^ pmod(ru_g, ru_x, RU_N)) | ru_msb;
+	return (ru_seed ^ pmod2(ru_t, ru_x)) | ru_msb;
 }
 
 int

--Boundary-00=_r7Tx/CZlykTZweJ--