1 1.16 andvar /* $NetBSD: randomid.c,v 1.16 2022/05/15 20:37:50 andvar Exp $ */ 2 1.1 itojun /* $KAME: ip6_id.c,v 1.8 2003/09/06 13:41:06 itojun Exp $ */ 3 1.1 itojun /* $OpenBSD: ip_id.c,v 1.6 2002/03/15 18:19:52 millert Exp $ */ 4 1.1 itojun 5 1.1 itojun /* 6 1.1 itojun * Copyright (C) 2003 WIDE Project. 7 1.1 itojun * All rights reserved. 8 1.1 itojun * 9 1.1 itojun * Redistribution and use in source and binary forms, with or without 10 1.1 itojun * modification, are permitted provided that the following conditions 11 1.1 itojun * are met: 12 1.1 itojun * 1. Redistributions of source code must retain the above copyright 13 1.1 itojun * notice, this list of conditions and the following disclaimer. 14 1.1 itojun * 2. Redistributions in binary form must reproduce the above copyright 15 1.1 itojun * notice, this list of conditions and the following disclaimer in the 16 1.1 itojun * documentation and/or other materials provided with the distribution. 17 1.1 itojun * 3. Neither the name of the project nor the names of its contributors 18 1.1 itojun * may be used to endorse or promote products derived from this software 19 1.1 itojun * without specific prior written permission. 20 1.1 itojun * 21 1.1 itojun * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 22 1.1 itojun * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 1.1 itojun * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 1.1 itojun * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 25 1.1 itojun * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 1.1 itojun * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 1.1 itojun * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 1.1 itojun * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 1.1 itojun * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 1.1 itojun * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 1.1 itojun * SUCH DAMAGE. 32 1.1 itojun */ 33 1.1 itojun 34 1.1 itojun /* 35 1.1 itojun * Copyright 1998 Niels Provos <provos (at) citi.umich.edu> 36 1.1 itojun * All rights reserved. 37 1.1 itojun * 38 1.1 itojun * Theo de Raadt <deraadt (at) openbsd.org> came up with the idea of using 39 1.1 itojun * such a mathematical system to generate more random (yet non-repeating) 40 1.1 itojun * ids to solve the resolver/named problem. But Niels designed the 41 1.1 itojun * actual system based on the constraints. 42 1.1 itojun * 43 1.1 itojun * Redistribution and use in source and binary forms, with or without 44 1.1 itojun * modification, are permitted provided that the following conditions 45 1.1 itojun * are met: 46 1.1 itojun * 1. Redistributions of source code must retain the above copyright 47 1.1 itojun * notice, this list of conditions and the following disclaimer. 48 1.1 itojun * 2. Redistributions in binary form must reproduce the above copyright 49 1.1 itojun * notice, this list of conditions and the following disclaimer in the 50 1.1 itojun * documentation and/or other materials provided with the distribution. 51 1.1 itojun * 52 1.1 itojun * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 53 1.1 itojun * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 54 1.1 itojun * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 55 1.1 itojun * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 56 1.1 itojun * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 57 1.1 itojun * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 58 1.1 itojun * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 59 1.1 itojun * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 60 1.1 itojun * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 61 1.1 itojun * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 62 1.1 itojun */ 63 1.1 itojun 64 1.1 itojun /* 65 1.1 itojun * seed = random (bits - 1) bit 66 1.1 itojun * n = prime, g0 = generator to n, 67 1.1 itojun * j = random so that gcd(j,n-1) == 1 68 1.1 itojun * g = g0^j mod n will be a generator again. 69 1.1 itojun * 70 1.1 itojun * X[0] = random seed. 71 1.1 itojun * X[n] = a*X[n-1]+b mod m is a Linear Congruential Generator 72 1.1 itojun * with a = 7^(even random) mod m, 73 1.1 itojun * b = random with gcd(b,m) == 1 74 1.1 itojun * m = constant and a maximal period of m-1. 75 1.1 itojun * 76 1.1 itojun * The transaction id is determined by: 77 1.1 itojun * id[n] = seed xor (g^X[n] mod n) 78 1.1 itojun * 79 1.15 andvar * Effectively the id is restricted to the lower (bits - 1) bits, thus 80 1.1 itojun * yielding two different cycles by toggling the msb on and off. 81 1.1 itojun * This avoids reuse issues caused by reseeding. 82 1.1 itojun */ 83 1.1 itojun 84 1.1 itojun #include <sys/cdefs.h> 85 1.1 itojun #if defined(LIBC_SCCS) && !defined(lint) 86 1.16 andvar __RCSID("$NetBSD: randomid.c,v 1.16 2022/05/15 20:37:50 andvar Exp $"); 87 1.1 itojun #endif 88 1.1 itojun 89 1.5 itojun #include "namespace.h" 90 1.5 itojun 91 1.1 itojun #include <sys/types.h> 92 1.1 itojun #include <sys/time.h> 93 1.1 itojun #include <stdlib.h> 94 1.2 tls #include <string.h> 95 1.1 itojun #include <errno.h> 96 1.1 itojun #include <randomid.h> 97 1.5 itojun 98 1.5 itojun #ifdef __weak_alias 99 1.5 itojun __weak_alias(randomid,_randomid) 100 1.5 itojun __weak_alias(randomid_new,_randomid_new) 101 1.5 itojun __weak_alias(randomid_delete,_randomid_delete) 102 1.5 itojun #endif 103 1.1 itojun 104 1.1 itojun struct randomconf { 105 1.1 itojun const int rc_bits; /* resulting bits */ 106 1.1 itojun const u_int32_t rc_max; /* Uniq cycle, avoid blackjack prediction */ 107 1.1 itojun const u_int32_t rc_gen; /* Starting generator */ 108 1.1 itojun const u_int32_t rc_n; /* ru_n: prime, ru_n - 1: product of pfacts[] */ 109 1.1 itojun const u_int32_t rc_agen; /* determine ru_a as ru_agen^(2*rand) */ 110 1.1 itojun const u_int32_t rc_m; /* ru_m = 2^x*3^y */ 111 1.1 itojun const u_int32_t rc_pfacts[4]; /* factors of ru_n */ 112 1.10 itojun const int rc_skip; /* skip values */ 113 1.1 itojun }; 114 1.1 itojun 115 1.1 itojun struct randomid_ctx { 116 1.1 itojun struct randomconf *ru_conf; 117 1.1 itojun #define ru_bits ru_conf->rc_bits 118 1.1 itojun #define ru_max ru_conf->rc_max 119 1.1 itojun #define ru_gen ru_conf->rc_gen 120 1.1 itojun #define ru_n ru_conf->rc_n 121 1.1 itojun #define ru_agen ru_conf->rc_agen 122 1.1 itojun #define ru_m ru_conf->rc_m 123 1.1 itojun #define ru_pfacts ru_conf->rc_pfacts 124 1.10 itojun #define ru_skip ru_conf->rc_skip 125 1.16 andvar long ru_out; /* Time after which will be reseeded */ 126 1.1 itojun u_int32_t ru_counter; 127 1.1 itojun u_int32_t ru_msb; 128 1.1 itojun 129 1.1 itojun u_int32_t ru_x; 130 1.10 itojun u_int32_t ru_seed, ru_seed2; 131 1.1 itojun u_int32_t ru_a, ru_b; 132 1.1 itojun u_int32_t ru_g; 133 1.13 christos time_t ru_reseed; 134 1.1 itojun }; 135 1.1 itojun 136 1.1 itojun static struct randomconf randomconf[] = { 137 1.1 itojun { 138 1.1 itojun 32, /* resulting bits */ 139 1.1 itojun 1000000000, /* Uniq cycle, avoid blackjack prediction */ 140 1.1 itojun 2, /* Starting generator */ 141 1.1 itojun 2147483629, /* RU_N-1 = 2^2*3^2*59652323 */ 142 1.1 itojun 7, /* determine ru_a as RU_AGEN^(2*rand) */ 143 1.1 itojun 1836660096, /* RU_M = 2^7*3^15 - don't change */ 144 1.1 itojun { 2, 3, 59652323, 0 }, /* factors of ru_n */ 145 1.10 itojun 3, /* skip values */ 146 1.1 itojun }, 147 1.1 itojun { 148 1.1 itojun 20, /* resulting bits */ 149 1.1 itojun 200000, /* Uniq cycle, avoid blackjack prediction */ 150 1.1 itojun 2, /* Starting generator */ 151 1.1 itojun 524269, /* RU_N-1 = 2^2*3^2*14563 */ 152 1.1 itojun 7, /* determine ru_a as RU_AGEN^(2*rand) */ 153 1.1 itojun 279936, /* RU_M = 2^7*3^7 - don't change */ 154 1.1 itojun { 2, 3, 14563, 0 }, /* factors of ru_n */ 155 1.10 itojun 3, /* skip values */ 156 1.1 itojun }, 157 1.1 itojun { 158 1.1 itojun 16, /* resulting bits */ 159 1.1 itojun 30000, /* Uniq cycle, avoid blackjack prediction */ 160 1.1 itojun 2, /* Starting generator */ 161 1.1 itojun 32749, /* RU_N-1 = 2^2*3*2729 */ 162 1.1 itojun 7, /* determine ru_a as RU_AGEN^(2*rand) */ 163 1.1 itojun 31104, /* RU_M = 2^7*3^5 - don't change */ 164 1.1 itojun { 2, 3, 2729, 0 }, /* factors of ru_n */ 165 1.10 itojun 0, /* skip values */ 166 1.1 itojun }, 167 1.1 itojun { 168 1.12 christos .rc_bits = -1, /* termination */ 169 1.1 itojun }, 170 1.1 itojun }; 171 1.1 itojun 172 1.1 itojun static u_int32_t pmod(u_int32_t, u_int32_t, u_int32_t); 173 1.1 itojun static void initid(struct randomid_ctx *); 174 1.1 itojun 175 1.1 itojun struct randomid_ctx *randomid_new(int, long); 176 1.1 itojun void randomid_delete(struct randomid_ctx *); 177 1.1 itojun u_int32_t randomid(struct randomid_ctx *); 178 1.1 itojun 179 1.1 itojun /* 180 1.1 itojun * Do a fast modular exponation, returned value will be in the range 181 1.1 itojun * of 0 - (mod-1) 182 1.1 itojun */ 183 1.1 itojun 184 1.1 itojun static u_int32_t 185 1.3 tls pmod(u_int32_t gen, u_int32_t expo, u_int32_t mod) 186 1.1 itojun { 187 1.1 itojun u_int64_t s, t, u; 188 1.1 itojun 189 1.1 itojun s = 1; 190 1.1 itojun t = gen; 191 1.3 tls u = expo; 192 1.1 itojun 193 1.1 itojun while (u) { 194 1.1 itojun if (u & 1) 195 1.1 itojun s = (s * t) % mod; 196 1.1 itojun u >>= 1; 197 1.1 itojun t = (t * t) % mod; 198 1.1 itojun } 199 1.1 itojun return ((u_int32_t)s & UINT32_MAX); 200 1.1 itojun } 201 1.1 itojun 202 1.1 itojun /* 203 1.14 msaitoh * Initializes the seed and chooses a suitable generator. Also toggles 204 1.1 itojun * the msb flag. The msb flag is used to generate two distinct 205 1.1 itojun * cycles of random numbers and thus avoiding reuse of ids. 206 1.1 itojun * 207 1.1 itojun * This function is called from id_randomid() when needed, an 208 1.1 itojun * application does not have to worry about it. 209 1.1 itojun */ 210 1.1 itojun static void 211 1.1 itojun initid(struct randomid_ctx *p) 212 1.1 itojun { 213 1.1 itojun u_int32_t j, i; 214 1.1 itojun int noprime = 1; 215 1.1 itojun struct timeval tv; 216 1.1 itojun 217 1.1 itojun p->ru_x = arc4random() % p->ru_m; 218 1.1 itojun 219 1.1 itojun /* (bits - 1) bits of random seed */ 220 1.1 itojun p->ru_seed = arc4random() & (~0U >> (32 - p->ru_bits + 1)); 221 1.10 itojun p->ru_seed2 = arc4random() & (~0U >> (32 - p->ru_bits + 1)); 222 1.1 itojun 223 1.1 itojun /* Determine the LCG we use */ 224 1.6 itojun p->ru_b = (arc4random() & (~0U >> (32 - p->ru_bits))) | 1; 225 1.6 itojun p->ru_a = pmod(p->ru_agen, 226 1.6 itojun (arc4random() & (~0U >> (32 - p->ru_bits))) & (~1U), p->ru_m); 227 1.1 itojun while (p->ru_b % 3 == 0) 228 1.1 itojun p->ru_b += 2; 229 1.1 itojun 230 1.1 itojun j = arc4random() % p->ru_n; 231 1.1 itojun 232 1.1 itojun /* 233 1.1 itojun * Do a fast gcd(j, RU_N - 1), so we can find a j with 234 1.1 itojun * gcd(j, RU_N - 1) == 1, giving a new generator for 235 1.1 itojun * RU_GEN^j mod RU_N 236 1.1 itojun */ 237 1.1 itojun while (noprime) { 238 1.1 itojun for (i = 0; p->ru_pfacts[i] > 0; i++) 239 1.1 itojun if (j % p->ru_pfacts[i] == 0) 240 1.1 itojun break; 241 1.1 itojun 242 1.1 itojun if (p->ru_pfacts[i] == 0) 243 1.1 itojun noprime = 0; 244 1.1 itojun else 245 1.1 itojun j = (j + 1) % p->ru_n; 246 1.1 itojun } 247 1.1 itojun 248 1.1 itojun p->ru_g = pmod(p->ru_gen, j, p->ru_n); 249 1.1 itojun p->ru_counter = 0; 250 1.1 itojun 251 1.1 itojun gettimeofday(&tv, NULL); 252 1.1 itojun p->ru_reseed = tv.tv_sec + p->ru_out; 253 1.1 itojun p->ru_msb = p->ru_msb ? 0 : (1U << (p->ru_bits - 1)); 254 1.1 itojun } 255 1.1 itojun 256 1.1 itojun struct randomid_ctx * 257 1.1 itojun randomid_new(int bits, long timeo) 258 1.1 itojun { 259 1.1 itojun struct randomconf *conf; 260 1.1 itojun struct randomid_ctx *ctx; 261 1.1 itojun 262 1.1 itojun if (timeo < RANDOMID_TIMEO_MIN) { 263 1.1 itojun errno = EINVAL; 264 1.1 itojun return (NULL); 265 1.1 itojun } 266 1.1 itojun 267 1.1 itojun for (conf = randomconf; conf->rc_bits > 0; conf++) { 268 1.1 itojun if (bits == conf->rc_bits) 269 1.1 itojun break; 270 1.1 itojun } 271 1.1 itojun 272 1.1 itojun /* unsupported bits */ 273 1.1 itojun if (bits != conf->rc_bits) { 274 1.1 itojun errno = ENOTSUP; 275 1.1 itojun return (NULL); 276 1.1 itojun } 277 1.1 itojun 278 1.1 itojun ctx = malloc(sizeof(*ctx)); 279 1.4 itojun if (!ctx) 280 1.4 itojun return (NULL); 281 1.4 itojun 282 1.1 itojun memset(ctx, 0, sizeof(*ctx)); 283 1.1 itojun ctx->ru_conf = conf; 284 1.1 itojun ctx->ru_out = timeo; 285 1.1 itojun 286 1.1 itojun return (ctx); 287 1.1 itojun } 288 1.1 itojun 289 1.1 itojun void 290 1.1 itojun randomid_delete(struct randomid_ctx *ctx) 291 1.1 itojun { 292 1.1 itojun 293 1.1 itojun memset(ctx, 0, sizeof(*ctx)); 294 1.1 itojun free(ctx); 295 1.1 itojun } 296 1.1 itojun 297 1.1 itojun u_int32_t 298 1.1 itojun randomid(struct randomid_ctx *p) 299 1.1 itojun { 300 1.1 itojun int i, n; 301 1.1 itojun struct timeval tv; 302 1.1 itojun 303 1.1 itojun gettimeofday(&tv, NULL); 304 1.1 itojun if (p->ru_counter >= p->ru_max || tv.tv_sec > p->ru_reseed) 305 1.1 itojun initid(p); 306 1.1 itojun 307 1.1 itojun /* Skip a random number of ids */ 308 1.10 itojun if (p->ru_skip) { 309 1.10 itojun n = arc4random() & p->ru_skip; 310 1.10 itojun if (p->ru_counter + n >= p->ru_max) 311 1.10 itojun initid(p); 312 1.10 itojun } else 313 1.10 itojun n = 0; 314 1.1 itojun 315 1.1 itojun for (i = 0; i <= n; i++) { 316 1.1 itojun /* Linear Congruential Generator */ 317 1.8 simonb p->ru_x = (u_int32_t)(((u_int64_t)p->ru_a * p->ru_x + p->ru_b) % p->ru_m); 318 1.1 itojun } 319 1.1 itojun 320 1.1 itojun p->ru_counter += i; 321 1.1 itojun 322 1.10 itojun return (p->ru_seed ^ pmod(p->ru_g, p->ru_seed2 + p->ru_x, p->ru_n)) | 323 1.1 itojun p->ru_msb; 324 1.1 itojun } 325