xref: /freebsd/usr.bin/random/randomize_fd.h (revision b3e7694832e81d7a904a10f525f8797b753bf0d3)
16ae1554aSColin Percival /*
26ae1554aSColin Percival  * Copyright (C) 2003 Sean Chittenden <seanc@FreeBSD.org>
36ae1554aSColin Percival  * All rights reserved.
46ae1554aSColin Percival  *
56ae1554aSColin Percival  * Redistribution and use in source and binary forms, with or without
66ae1554aSColin Percival  * modification, are permitted provided that the following conditions
76ae1554aSColin Percival  * are met:
86ae1554aSColin Percival  * 1. Redistributions of source code must retain the above copyright
96ae1554aSColin Percival  *    notice, this list of conditions and the following disclaimer.
106ae1554aSColin Percival  * 2. Redistributions in binary form must reproduce the above copyright
116ae1554aSColin Percival  *    notice, this list of conditions and the following disclaimer in the
126ae1554aSColin Percival  *    documentation and/or other materials provided with the distribution.
136ae1554aSColin Percival  *
146ae1554aSColin Percival  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
156ae1554aSColin Percival  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
166ae1554aSColin Percival  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
176ae1554aSColin Percival  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
186ae1554aSColin Percival  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
196ae1554aSColin Percival  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
206ae1554aSColin Percival  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
216ae1554aSColin Percival  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
226ae1554aSColin Percival  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
236ae1554aSColin Percival  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
246ae1554aSColin Percival  * SUCH DAMAGE.
256ae1554aSColin Percival  */
266ae1554aSColin Percival 
276ae1554aSColin Percival #ifndef __RANDOMIZE_FD__
286ae1554aSColin Percival #define __RANDOMIZE_FD__
296ae1554aSColin Percival 
306ae1554aSColin Percival #define RANDOM_TYPE_UNSET 0
316ae1554aSColin Percival #define RANDOM_TYPE_LINES 1
326ae1554aSColin Percival #define RANDOM_TYPE_WORDS 2
336ae1554aSColin Percival 
346ae1554aSColin Percival /* The multiple instance single integer key */
356ae1554aSColin Percival struct rand_node {
366ae1554aSColin Percival 	u_char *cp;
376ae1554aSColin Percival 	u_int len;
386ae1554aSColin Percival 	struct rand_node *next;
396ae1554aSColin Percival };
406ae1554aSColin Percival 
416ae1554aSColin Percival int randomize_fd(int fd, int type, int unique, double denom);
426ae1554aSColin Percival 
43*06257a71SConrad Meyer /*
44*06257a71SConrad Meyer  * Generates a random number uniformly in the range [0.0, 1.0).
45*06257a71SConrad Meyer  */
46*06257a71SConrad Meyer static inline double
random_unit_float(void)47*06257a71SConrad Meyer random_unit_float(void)
48*06257a71SConrad Meyer {
49*06257a71SConrad Meyer 	static const uint64_t denom = (1ull << 53);
50*06257a71SConrad Meyer 	static const uint64_t mask = denom - 1;
51*06257a71SConrad Meyer 
52*06257a71SConrad Meyer 	uint64_t rand64;
53*06257a71SConrad Meyer 
54*06257a71SConrad Meyer 	/*
55*06257a71SConrad Meyer 	 * arc4random_buf(...) in this use generates integer outputs in [0,
56*06257a71SConrad Meyer 	 * UINT64_MAX].
57*06257a71SConrad Meyer 	 *
58*06257a71SConrad Meyer 	 * The double mantissa only has 53 bits, so we uniformly mask off the
59*06257a71SConrad Meyer 	 * high 11 bits and then floating-point divide by 2^53 to achieve a
60*06257a71SConrad Meyer 	 * result in [0, 1).
61*06257a71SConrad Meyer 	 *
62*06257a71SConrad Meyer 	 * We are not allowed to emit 1.0, so denom must be one greater than
63*06257a71SConrad Meyer 	 * the possible range of the preceeding step.
64*06257a71SConrad Meyer 	 */
65*06257a71SConrad Meyer 	arc4random_buf(&rand64, sizeof(rand64));
66*06257a71SConrad Meyer 	rand64 &= mask;
67*06257a71SConrad Meyer 	return ((double)rand64 / denom);
68*06257a71SConrad Meyer }
69*06257a71SConrad Meyer 
70*06257a71SConrad Meyer /*
71*06257a71SConrad Meyer  * Returns true with probability 1 / denom (a floating point number >= 1).
72*06257a71SConrad Meyer  * Otherwise, returns false.
73*06257a71SConrad Meyer  */
74*06257a71SConrad Meyer static inline bool
random_uniform_denom(double denom)75*06257a71SConrad Meyer random_uniform_denom(double denom)
76*06257a71SConrad Meyer {
77*06257a71SConrad Meyer 	return ((uint64_t)(denom * random_unit_float()) == 0);
78*06257a71SConrad Meyer }
796ae1554aSColin Percival #endif
80