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--