/src/bind9/lib/isc/random.c
Line | Count | Source |
1 | | /* |
2 | | * Copyright (C) Internet Systems Consortium, Inc. ("ISC") |
3 | | * |
4 | | * SPDX-License-Identifier: MPL-2.0 |
5 | | * |
6 | | * This Source Code Form is subject to the terms of the Mozilla Public |
7 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
8 | | * file, you can obtain one at https://mozilla.org/MPL/2.0/. |
9 | | * |
10 | | * See the COPYRIGHT file distributed with this work for additional |
11 | | * information regarding copyright ownership. |
12 | | */ |
13 | | |
14 | | /* |
15 | | * Portions of isc_random_uniform(): |
16 | | * |
17 | | * Copyright (c) 1996, David Mazieres <dm@uun.org> |
18 | | * Copyright (c) 2008, Damien Miller <djm@openbsd.org> |
19 | | * |
20 | | * Permission to use, copy, modify, and distribute this software for any |
21 | | * purpose with or without fee is hereby granted, provided that the above |
22 | | * copyright notice and this permission notice appear in all copies. |
23 | | * |
24 | | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
25 | | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
26 | | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
27 | | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
28 | | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
29 | | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
30 | | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
31 | | */ |
32 | | |
33 | | #if !HAVE_ARC4RANDOM || defined(__linux__) |
34 | | |
35 | | #include <inttypes.h> |
36 | | #include <stdio.h> |
37 | | |
38 | | #include <isc/os.h> |
39 | | #include <isc/random.h> |
40 | | #include <isc/thread.h> |
41 | | #include <isc/util.h> |
42 | | #include <isc/uv.h> |
43 | | |
44 | 0 | #define ISC_RANDOM_BUFSIZE (ISC_OS_CACHELINE_SIZE / sizeof(uint32_t)) |
45 | | |
46 | | thread_local static uint32_t isc__random_pool[ISC_RANDOM_BUFSIZE]; |
47 | | thread_local static size_t isc__random_pos = ISC_RANDOM_BUFSIZE; |
48 | | |
49 | | uint32_t |
50 | 8.86M | isc_random32(void) { |
51 | 8.86M | #if FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION |
52 | | /* |
53 | | * A fixed stream of numbers helps with problem reproduction when |
54 | | * fuzzing. The first result needs to be non-zero as expected by |
55 | | * random_test.c (it starts with ISC_RANDOM_BUFSIZE, see above). |
56 | | */ |
57 | 8.86M | return (uint32_t)(isc__random_pos++); |
58 | 0 | #endif /* if FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */ |
59 | | |
60 | 0 | if (isc__random_pos == ISC_RANDOM_BUFSIZE) { |
61 | 0 | isc_random_buf(isc__random_pool, sizeof(isc__random_pool)); |
62 | 0 | isc__random_pos = 0; |
63 | 0 | } |
64 | |
|
65 | 0 | return isc__random_pool[isc__random_pos++]; |
66 | 8.86M | } |
67 | | |
68 | | void |
69 | 0 | isc_random_buf(void *buf, size_t buflen) { |
70 | 0 | REQUIRE(buflen == 0 || buf != NULL); |
71 | |
|
72 | 0 | if (buf == NULL || buflen == 0) { |
73 | 0 | return; |
74 | 0 | } |
75 | | |
76 | 0 | int r = uv_random(NULL, NULL, buf, buflen, 0, NULL); |
77 | 0 | UV_RUNTIME_CHECK(uv_random, r); |
78 | 0 | } |
79 | | |
80 | | uint32_t |
81 | 8.86M | isc_random_uniform(uint32_t limit) { |
82 | | /* |
83 | | * Daniel Lemire's nearly-divisionless unbiased bounded random numbers. |
84 | | * |
85 | | * https://lemire.me/blog/?p=17551 |
86 | | * |
87 | | * The raw random number generator `next()` returns a 32-bit value. |
88 | | * We do a 64-bit multiply `next() * limit` and treat the product as a |
89 | | * 32.32 fixed-point value less than the limit. Our result will be the |
90 | | * integer part (upper 32 bits), and we will use the fraction part |
91 | | * (lower 32 bits) to determine whether or not we need to resample. |
92 | | */ |
93 | 8.86M | uint64_t num = (uint64_t)isc_random32() * (uint64_t)limit; |
94 | | /* |
95 | | * In the fast path, we avoid doing a division in most cases by |
96 | | * comparing the fraction part of `num` with the limit, which is |
97 | | * a slight over-estimate for the exact resample threshold. |
98 | | */ |
99 | 8.86M | if ((uint32_t)(num) < limit) { |
100 | | /* |
101 | | * We are in the slow path where we re-do the approximate test |
102 | | * more accurately. The exact threshold for the resample loop |
103 | | * is the remainder after dividing the raw RNG limit `1 << 32` |
104 | | * by the caller's limit. We use a trick to calculate it |
105 | | * within 32 bits: |
106 | | * |
107 | | * (1 << 32) % limit |
108 | | * == ((1 << 32) - limit) % limit |
109 | | * == (uint32_t)(-limit) % limit |
110 | | * |
111 | | * This division is safe: we know that `limit` is strictly |
112 | | * greater than zero because of the slow-path test above. |
113 | | */ |
114 | 1 | uint32_t residue = (uint32_t)(-limit) % limit; |
115 | | /* |
116 | | * Unless we get one of `N = (1 << 32) - residue` valid |
117 | | * values, we reject the sample. This `N` is a multiple of |
118 | | * `limit`, so our results will be unbiased; and `N` is the |
119 | | * largest multiple that fits in 32 bits, so rejections are as |
120 | | * rare as possible. |
121 | | * |
122 | | * There are `limit` possible values for the integer part of |
123 | | * our fixed-point number. Each one corresponds to `N/limit` |
124 | | * or `N/limit + 1` possible fraction parts. For our result to |
125 | | * be unbiased, every possible integer part must have the same |
126 | | * number of possible valid fraction parts. So, when we get |
127 | | * the superfluous value in the `N/limit + 1` cases, we need |
128 | | * to reject and resample. |
129 | | * |
130 | | * Because of the multiplication, the possible values in the |
131 | | * fraction part are equally spaced by `limit`, with varying |
132 | | * gaps at each end of the fraction's 32-bit range. We will |
133 | | * choose a range of size `N` (a multiple of `limit`) into |
134 | | * which valid fraction values must fall, with the rest of the |
135 | | * 32-bit range covered by the `residue`. Lemire's paper says |
136 | | * that exactly `N/limit` possible values spaced apart by |
137 | | * `limit` will fit into our size `N` valid range, regardless |
138 | | * of the size of the end gaps, the phase alignment of the |
139 | | * values, or the position of the range. |
140 | | * |
141 | | * So, when a fraction value falls in the `residue` outside |
142 | | * our valid range, it is superfluous, and we resample. |
143 | | */ |
144 | 1 | while ((uint32_t)(num) < residue) { |
145 | 0 | num = (uint64_t)isc_random32() * (uint64_t)limit; |
146 | 0 | } |
147 | 1 | } |
148 | | /* |
149 | | * Return the integer part (upper 32 bits). |
150 | | */ |
151 | 8.86M | return (uint32_t)(num >> 32); |
152 | 8.86M | } |
153 | | |
154 | | #endif /* HAVE_ARC4RANDOM && !defined(__linux__) */ |