From cfbab92fdbc99951117bbe2100756ef7fb066e11 Mon Sep 17 00:00:00 2001 From: itojun Date: Tue, 9 Sep 2003 22:16:58 +0000 Subject: [PATCH] use randomid(3). actually generate random ID for DNS queries (previous fix was incomplete) --- lib/libc/net/res_init.c | 211 +----------------------------------- lib/libc/net/res_mkquery.c | 16 ++- lib/libc/rpc/__rpc_getxid.c | 189 +++++--------------------------- 3 files changed, 40 insertions(+), 376 deletions(-) diff --git a/lib/libc/net/res_init.c b/lib/libc/net/res_init.c index 3bdf8982820d..0615ef2fb489 100644 --- a/lib/libc/net/res_init.c +++ b/lib/libc/net/res_init.c @@ -1,4 +1,4 @@ -/* $NetBSD: res_init.c,v 1.44 2003/09/06 22:47:56 christos Exp $ */ +/* $NetBSD: res_init.c,v 1.45 2003/09/09 22:16:58 itojun Exp $ */ /*- * Copyright (c) 1985, 1989, 1993 @@ -55,7 +55,7 @@ static char sccsid[] = "@(#)res_init.c 8.1 (Berkeley) 6/7/93"; static char rcsid[] = "Id: res_init.c,v 8.8 1997/06/01 20:34:37 vixie Exp "; #else -__RCSID("$NetBSD: res_init.c,v 1.44 2003/09/06 22:47:56 christos Exp $"); +__RCSID("$NetBSD: res_init.c,v 1.45 2003/09/09 22:16:58 itojun Exp $"); #endif #endif /* LIBC_SCCS and not lint */ @@ -168,15 +168,6 @@ res_init() _res.retry = 4; if (!(_res.options & RES_INIT)) _res.options = RES_DEFAULT; - - /* - * This one used to initialize implicitly to zero, so unless the app - * has set it to something in particular, we can randomize it now. - */ - if (!_res.id) - _res.id = res_randomid(); -#else - _res.id = res_randomid(); #endif #ifdef USELOOPBACK @@ -579,201 +570,3 @@ net_mask(in) /* XXX - should really use system's version of this */ return (htonl(IN_CLASSB_NET)); return (htonl(IN_CLASSC_NET)); } - -/* $OpenBSD: res_random.c,v 1.12 2002/06/27 10:14:02 itojun Exp $ */ - -/* - * Copyright 1997 Niels Provos - * All rights reserved. - * - * Theo de Raadt came up with the idea of using - * such a mathematical system to generate more random (yet non-repeating) - * ids to solve the resolver/named problem. But Niels designed the - * actual system based on the constraints. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Niels Provos. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * seed = random 15bit - * n = prime, g0 = generator to n, - * j = random so that gcd(j,n-1) == 1 - * g = g0^j mod n will be a generator again. - * - * X[0] = random seed. - * X[n] = a*X[n-1]+b mod m is a Linear Congruential Generator - * with a = 7^(even random) mod m, - * b = random with gcd(b,m) == 1 - * m = 31104 and a maximal period of m-1. - * - * The transaction id is determined by: - * id[n] = seed xor (g^X[n] mod n) - * - * Effectivly the id is restricted to the lower 15 bits, thus - * yielding two different cycles by toggling the msb on and off. - * This avoids reuse issues caused by reseeding. - * - * The 16 bit space is very small and brute force attempts are - * entirly feasible, we skip a random number of transaction ids - * so that an attacker will not get sequential ids. - */ - -#define RU_OUT 180 /* Time after wich will be reseeded */ -#define RU_MAX 30000 /* Uniq cycle, avoid blackjack prediction */ -#define RU_GEN 2 /* Starting generator */ -#define RU_N 32749 /* RU_N-1 = 2*2*3*2729 */ -#define RU_AGEN 7 /* determine ru_a as RU_AGEN^(2*rand) */ -#define RU_M 31104 /* RU_M = 2^7*3^5 - don't change */ - -#define PFAC_N 3 -const static u_int16_t pfacts[PFAC_N] = { - 2, - 3, - 2729 -}; - -static u_int16_t ru_x; -static u_int16_t ru_seed, ru_seed2; -static u_int16_t ru_a, ru_b; -static u_int16_t ru_g; -static u_int16_t ru_counter = 0; -static u_int16_t ru_msb = 0; -static long ru_reseed; -static u_int32_t ru_tmp; /* Storage for unused random */ - -static u_int16_t pmod(u_int16_t, u_int16_t, u_int16_t); -static void res_initid(void); - -/* - * Do a fast modular exponation, returned value will be in the range - * of 0 - (mod-1) - */ - -static u_int16_t -pmod(u_int16_t gen, u_int16_t expo, u_int16_t mod) -{ - u_int16_t s, t, u; - - s = 1; - t = gen; - u = expo; - - while (u) { - if (u & 1) - s = (s * t) % mod; - u >>= 1; - t = (t * t) % mod; - } - return (s); -} - -/* - * Initializes the seed and chooses a suitable generator. Also toggles - * the msb flag. The msb flag is used to generate two distinct - * cycles of random numbers and thus avoiding reuse of ids. - * - * This function is called from res_randomid() when needed, an - * application does not have to worry about it. - */ -static void -res_initid(void) -{ - u_int16_t j, i; - int noprime = 1; - struct timeval tv; - - ru_tmp = arc4random(); - ru_x = (ru_tmp & 0xFFFF) % RU_M; - - /* 15 bits of random seed */ - ru_seed = (ru_tmp >> 16) & 0x7FFF; - ru_tmp = arc4random(); - ru_seed2 = ru_tmp & 0x7FFF; - - ru_tmp = arc4random(); - - /* Determine the LCG we use */ - ru_b = (ru_tmp & 0xfffe) | 1; - ru_a = pmod(RU_AGEN, (ru_tmp >> 16) & 0xfffe, RU_M); - while (ru_b % 3 == 0) - ru_b += 2; - - ru_tmp = arc4random(); - j = ru_tmp % RU_N; - ru_tmp = ru_tmp >> 16; - - /* - * Do a fast gcd(j,RU_N-1), so we can find a j with - * gcd(j, RU_N-1) == 1, giving a new generator for - * RU_GEN^j mod RU_N - */ - - while (noprime) { - for (i = 0; i < PFAC_N; i++) - if (j % pfacts[i] == 0) - break; - - if (i >= PFAC_N) - noprime = 0; - else - j = (j + 1) % RU_N; - } - - ru_g = pmod(RU_GEN, j, RU_N); - ru_counter = 0; - - gettimeofday(&tv, NULL); - ru_reseed = tv.tv_sec + RU_OUT; - ru_msb = ru_msb == 0x8000 ? 0 : 0x8000; -} - -u_int -res_randomid(void) -{ - int i, n; - struct timeval tv; - - gettimeofday(&tv, NULL); - if (ru_counter >= RU_MAX || tv.tv_sec > ru_reseed) - res_initid(); - - if (!ru_tmp) - ru_tmp = arc4random(); - - /* Skip a random number of ids */ - n = ru_tmp & 0x7; ru_tmp = ru_tmp >> 3; - if (ru_counter + n >= RU_MAX) - res_initid(); - - for (i = 0; i <= n; i++) { - /* Linear Congruential Generator */ - ru_x = (ru_a * ru_x + ru_b) % RU_M; - } - - ru_counter += i; - - return (ru_seed ^ pmod(ru_g, ru_seed2 ^ ru_x, RU_N)) | ru_msb; -} diff --git a/lib/libc/net/res_mkquery.c b/lib/libc/net/res_mkquery.c index 13a44c13d8e8..2a6fcea4f842 100644 --- a/lib/libc/net/res_mkquery.c +++ b/lib/libc/net/res_mkquery.c @@ -1,4 +1,4 @@ -/* $NetBSD: res_mkquery.c,v 1.24 2003/08/07 16:43:14 agc Exp $ */ +/* $NetBSD: res_mkquery.c,v 1.25 2003/09/09 22:16:58 itojun Exp $ */ /*- * Copyright (c) 1985, 1993 @@ -55,7 +55,7 @@ static char sccsid[] = "@(#)res_mkquery.c 8.1 (Berkeley) 6/4/93"; static char rcsid[] = "Id: res_mkquery.c,v 8.5 1996/08/27 08:33:28 vixie Exp "; #else -__RCSID("$NetBSD: res_mkquery.c,v 1.24 2003/08/07 16:43:14 agc Exp $"); +__RCSID("$NetBSD: res_mkquery.c,v 1.25 2003/09/09 22:16:58 itojun Exp $"); #endif #endif /* LIBC_SCCS and not lint */ @@ -72,6 +72,7 @@ __RCSID("$NetBSD: res_mkquery.c,v 1.24 2003/08/07 16:43:14 agc Exp $"); #include #include #include +#include #if defined(_LIBC) && defined(__weak_alias) __weak_alias(res_mkquery,_res_mkquery) @@ -97,11 +98,20 @@ res_mkquery(op, dname, class, type, data, datalen, newrr_in, buf, buflen) register u_char *cp, *ep; register int n; u_char *dnptrs[20], **dpp, **lastdnptr; + static randomid_t ctx = NULL;; _DIAGASSERT(dname != NULL); /* data may be NULL */ /* newrr_in is not used */ + if (!ctx) { + ctx = randomid_new(16, RANDOMID_TIMEO_DEFAULT); + if (!ctx) { + h_errno = NETDB_INTERNAL; + return (-1); + } + } + if ((_res.options & RES_INIT) == 0 && res_init() == -1) { h_errno = NETDB_INTERNAL; return (-1); @@ -127,7 +137,7 @@ res_mkquery(op, dname, class, type, data, datalen, newrr_in, buf, buflen) return(-1); (void)memset(buf, 0, HFIXEDSZ); hp = (HEADER *)(void *)buf; - hp->id = htons(++_res.id); + hp->id = htons(_res.id = (u_short)randomid(ctx)); hp->opcode = op; hp->rd = (_res.options & RES_RECURSE) != 0; hp->rcode = NOERROR; diff --git a/lib/libc/rpc/__rpc_getxid.c b/lib/libc/rpc/__rpc_getxid.c index 1dec03d8d095..9c2072487ca4 100644 --- a/lib/libc/rpc/__rpc_getxid.c +++ b/lib/libc/rpc/__rpc_getxid.c @@ -1,15 +1,10 @@ -/* $NetBSD: __rpc_getxid.c,v 1.1 2003/09/09 03:56:23 itojun Exp $ */ +/* $NetBSD: __rpc_getxid.c,v 1.2 2003/09/09 22:16:58 itojun Exp $ */ /* $OpenBSD: ip_id.c,v 1.6 2002/03/15 18:19:52 millert Exp $ */ /* - * Copyright 1998 Niels Provos + * Copyright (C) 2003 WIDE Project. * All rights reserved. * - * Theo de Raadt came up with the idea of using - * such a mathematical system to generate more random (yet non-repeating) - * ids to solve the resolver/named problem. But Niels designed the - * actual system based on the constraints. - * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -18,179 +13,45 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Niels Provos. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * seed = random 31bit - * n = prime, g0 = generator to n, - * j = random so that gcd(j,n-1) == 1 - * g = g0^j mod n will be a generator again. - * - * X[0] = random seed. - * X[n] = a*X[n-1]+b mod m is a Linear Congruential Generator - * with a = 7^(even random) mod m, - * b = random with gcd(b,m) == 1 - * m = 1836660096 and a maximal period of m-1. - * - * The transaction id is determined by: - * id[n] = seed xor (g^X[n] mod n) - * - * Effectivly the id is restricted to the lower 31 bits, thus - * yielding two different cycles by toggling the msb on and off. - * This avoids reuse issues caused by reseeding. + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. */ #include #if defined(LIBC_SCCS) && !defined(lint) -__RCSID("$NetBSD: __rpc_getxid.c,v 1.1 2003/09/09 03:56:23 itojun Exp $"); +__RCSID("$NetBSD: __rpc_getxid.c,v 1.2 2003/09/09 22:16:58 itojun Exp $"); #endif #include -#include + #include +#include #include #include "rpc_internal.h" -#define RU_OUT 180 /* Time after wich will be reseeded */ -#define RU_MAX 1000000000 /* Uniq cycle, avoid blackjack prediction */ -#define RU_GEN 2 /* Starting generator */ -#define RU_N 2147483629 /* RU_N-1 = 2^2*3^2*59652323 */ -#define RU_AGEN 7 /* determine ru_a as RU_AGEN^(2*rand) */ -#define RU_M 1836660096 /* RU_M = 2^7*3^15 - don't change */ - -#define PFAC_N 3 -const static u_int32_t pfacts[PFAC_N] = { - 2, - 3, - 59652323 -}; - -static u_int32_t ru_x; -static u_int32_t ru_seed, ru_seed2; -static u_int32_t ru_a, ru_b; -static u_int32_t ru_g; -static u_int32_t ru_counter = 0; -static u_int32_t ru_msb = 0; -static long ru_reseed; - -static u_int32_t pmod(u_int32_t, u_int32_t, u_int32_t); -static void initid(void); - -/* - * Do a fast modular exponation, returned value will be in the range - * of 0 - (mod-1) - */ -static u_int32_t -pmod(u_int32_t gen, u_int32_t exp, u_int32_t mod) -{ - u_int64_t s, t, u; - - s = 1; - t = gen; - u = exp; - - while (u) { - if (u & 1) - s = (s * t) % mod; - u >>= 1; - t = (t * t) % mod; - } - return ((u_int32_t)s & 0xffffffff); -} - -/* - * Initalizes the seed and chooses a suitable generator. Also toggles - * the msb flag. The msb flag is used to generate two distinct - * cycles of random numbers and thus avoiding reuse of ids. - * - * This function is called from id_randomid() when needed, an - * application does not have to worry about it. - */ -static void -initid(void) -{ - u_int32_t j, i; - int noprime = 1; - struct timeval tv; - - ru_x = arc4random() % RU_M; - - /* 31 bits of random seed */ - ru_seed = arc4random() & INT32_MAX; - ru_seed2 = arc4random() & INT32_MAX; - - /* Determine the LCG we use */ - ru_b = arc4random() | 1; - ru_a = pmod(RU_AGEN, arc4random() & (~1U), RU_M); - while (ru_b % 3 == 0) - ru_b += 2; - - j = arc4random() % RU_N; - - /* - * Do a fast gcd(j,RU_N-1), so we can find a j with - * gcd(j, RU_N-1) == 1, giving a new generator for - * RU_GEN^j mod RU_N - */ - while (noprime) { - for (i = 0; i < PFAC_N; i++) - if (j % pfacts[i] == 0) - break; - - if (i >= PFAC_N) - noprime = 0; - else - j = (j + 1) % RU_N; - } - - ru_g = pmod(RU_GEN, j, RU_N); - ru_counter = 0; - - gettimeofday(&tv, NULL); - ru_reseed = tv.tv_sec + RU_OUT; - ru_msb = ru_msb ? 0 : 0x80000000; -} - u_int32_t __rpc_getxid(void) { - int i, n; - u_int32_t tmp; - struct timeval tv; + static randomid_t ctx = NULL; - gettimeofday(&tv, NULL); - if (ru_counter >= RU_MAX || tv.tv_sec > ru_reseed) - initid(); - - tmp = arc4random(); - - /* Skip a random number of ids */ - n = tmp & 0x3; tmp = tmp >> 2; - if (ru_counter + n >= RU_MAX) - initid(); - - for (i = 0; i <= n; i++) { - /* Linear Congruential Generator */ - ru_x = (ru_a * ru_x + ru_b) % RU_M; + if (!ctx) { + ctx = randomid_new(32, RANDOMID_TIMEO_DEFAULT); + if (!ctx) + abort(); } - ru_counter += i; - - return (ru_seed ^ pmod(ru_g, ru_seed2 ^ ru_x,RU_N)) | ru_msb; + return randomid(ctx); }