diff --git a/lib/isc/entropy.c b/lib/isc/entropy.c deleted file mode 100644 index a037960bd18..00000000000 --- a/lib/isc/entropy.c +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (C) Internet Systems Consortium, Inc. ("ISC") - * - * SPDX-License-Identifier: MPL-2.0 - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, you can obtain one at https://mozilla.org/MPL/2.0/. - * - * See the COPYRIGHT file distributed with this work for additional - * information regarding copyright ownership. - */ - -#include -#include -#include -#include - -void -isc_entropy_get(void *buf, size_t buflen) { - int r = uv_random(NULL, NULL, buf, buflen, 0, NULL); - - UV_RUNTIME_CHECK(uv_random, r); -} diff --git a/lib/isc/hash.c b/lib/isc/hash.c index 387e2373cd1..49b942ef5bc 100644 --- a/lib/isc/hash.c +++ b/lib/isc/hash.c @@ -16,7 +16,6 @@ #include #include -#include #include /* IWYU pragma: keep */ #include #include @@ -35,7 +34,7 @@ isc__hash_initialize(void) { */ uint8_t key[16] = { 1 }; #if !FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION - isc_entropy_get(key, sizeof(key)); + isc_random_buf(key, sizeof(key)); #endif /* if FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */ STATIC_ASSERT(sizeof(key) >= sizeof(isc_hash_key), "sizeof(key) < sizeof(isc_hash_key)"); diff --git a/lib/isc/hashmap.c b/lib/isc/hashmap.c index d8c2bd58ae7..87b1a3f21a3 100644 --- a/lib/isc/hashmap.c +++ b/lib/isc/hashmap.c @@ -32,7 +32,6 @@ #include #include -#include #include #include #include diff --git a/lib/isc/include/isc/entropy.h b/lib/isc/include/isc/entropy.h deleted file mode 100644 index 81c2ed7cac4..00000000000 --- a/lib/isc/include/isc/entropy.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) Internet Systems Consortium, Inc. ("ISC") - * - * SPDX-License-Identifier: MPL-2.0 - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, you can obtain one at https://mozilla.org/MPL/2.0/. - * - * See the COPYRIGHT file distributed with this work for additional - * information regarding copyright ownership. - */ - -#pragma once - -#include - -/*! \file isc/entropy.h - * \brief Implements wrapper around CSPRNG cryptographic library calls - * for getting cryptographically secure pseudo-random numbers. - * - * Uses synchronous version of uv_random(). - */ - -void -isc_entropy_get(void *buf, size_t buflen); -/*!< - * \brief Get cryptographically-secure pseudo-random data. - */ diff --git a/lib/isc/include/isc/nonce.h b/lib/isc/include/isc/nonce.h index ce15b7e12a2..b61270bd825 100644 --- a/lib/isc/include/isc/nonce.h +++ b/lib/isc/include/isc/nonce.h @@ -15,12 +15,16 @@ #include +#include + /*! \file isc/nonce.h * \brief Provides a function for generating an arbitrarily long nonce. */ -void -isc_nonce_buf(void *buf, size_t buflen); +static inline void +isc_nonce_buf(void *buf, size_t buflen) { + isc_random_buf(buf, buflen); +} /*!< * Fill 'buf', up to 'buflen' bytes, with random data from the * crypto provider's random function. diff --git a/lib/isc/include/isc/random.h b/lib/isc/include/isc/random.h index 213e979ec6b..efee399095e 100644 --- a/lib/isc/include/isc/random.h +++ b/lib/isc/include/isc/random.h @@ -19,23 +19,16 @@ #include /*! \file isc/random.h - * \brief Implements wrapper around a non-cryptographically secure + * \brief Implements wrapper around a cryptographically secure * pseudo-random number generator. * */ -uint8_t -isc_random8(void); -/*!< - * \brief Returns a single 8-bit random value. - */ - -uint16_t -isc_random16(void); -/*!< - * \brief Returns a single 16-bit random value. - */ - +#if HAVE_ARC4RANDOM && !defined(__linux__) +#define isc_random32() arc4random() +#define isc_random_buf(buf, buflen) arc4random_buf(buf, buflen) +#define isc_random_uniform(upper_bound) arc4random_uniform(upper_bound) +#else /* HAVE_ARC4RANDOM && !defined(__linux__) */ uint32_t isc_random32(void); /*!< @@ -64,3 +57,21 @@ isc_random_uniform(uint32_t upper_bound); * resample is very small when the upper_bound is small, rising to 0.5 * when upper_bound is UINT32_MAX/2. */ + +#endif /* HAVE_ARC4RANDOM && !defined(__linux__) */ + +static inline uint8_t +isc_random8(void) { + return (uint8_t)isc_random32(); +} +/*!< + * \brief Returns a single 8-bit random value. + */ + +static inline uint16_t +isc_random16(void) { + return (uint16_t)isc_random32(); +} +/*!< + * \brief Returns a single 16-bit random value. + */ diff --git a/lib/isc/meson.build b/lib/isc/meson.build index 223d6796f2a..1be850c7c80 100644 --- a/lib/isc/meson.build +++ b/lib/isc/meson.build @@ -73,7 +73,6 @@ isc_srcset.add( 'counter.c', 'crypto.c', 'dir.c', - 'entropy.c', 'errno.c', 'errno2result.c', 'error.c', @@ -102,7 +101,6 @@ isc_srcset.add( 'net.c', 'netaddr.c', 'netscope.c', - 'nonce.c', 'openssl_shim.c', 'os.c', 'parseint.c', diff --git a/lib/isc/nonce.c b/lib/isc/nonce.c deleted file mode 100644 index 316498a6136..00000000000 --- a/lib/isc/nonce.c +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (C) Internet Systems Consortium, Inc. ("ISC") - * - * SPDX-License-Identifier: MPL-2.0 - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, you can obtain one at https://mozilla.org/MPL/2.0/. - * - * See the COPYRIGHT file distributed with this work for additional - * information regarding copyright ownership. - */ - -#include -#include - -void -isc_nonce_buf(void *buf, size_t buflen) { - isc_entropy_get(buf, buflen); -} diff --git a/lib/isc/random.c b/lib/isc/random.c index 88efd21c4e6..1367fd5a121 100644 --- a/lib/isc/random.c +++ b/lib/isc/random.c @@ -30,126 +30,55 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#if !HAVE_ARC4RANDOM || defined(__linux__) + #include -#include -#include -#include +#include -#include +#include #include -#include #include -#include #include +#include -/* - * Written in 2018 by David Blackman and Sebastiano Vigna (vigna@acm.org) - * - * To the extent possible under law, the author has dedicated all - * copyright and related and neighboring rights to this software to the - * public domain worldwide. This software is distributed without any - * warranty. - * - * See . - */ - -/* - * This is xoshiro128** 1.0, our 32-bit all-purpose, rock-solid generator. - * It has excellent (sub-ns) speed, a state size (128 bits) that is large - * enough for mild parallelism, and it passes all tests we are aware of. - * - * The state must be seeded so that it is not everywhere zero. - */ - -static thread_local bool initialized = false; -static thread_local uint32_t seed[4] = { 0 }; - -static uint32_t -rotl(const uint32_t x, int k) { - return (x << k) | (x >> (32 - k)); -} - -static uint32_t -next(void) { - uint32_t result_starstar, t; - - result_starstar = rotl(seed[0] * 5, 7) * 9; - t = seed[1] << 9; - - seed[2] ^= seed[0]; - seed[3] ^= seed[1]; - seed[1] ^= seed[2]; - seed[0] ^= seed[3]; - - seed[2] ^= t; - - seed[3] = rotl(seed[3], 11); - - return result_starstar; -} +#define ISC_RANDOM_BUFSIZE (ISC_OS_CACHELINE_SIZE / sizeof(uint32_t)) -static void -isc__random_initialize(void) { - if (initialized) { - return; - } +thread_local static uint32_t isc__random_pool[ISC_RANDOM_BUFSIZE]; +thread_local static size_t isc__random_pos = ISC_RANDOM_BUFSIZE; +uint32_t +isc_random32(void) { #if FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION /* - * A fixed seed helps with problem reproduction when fuzzing. It must be - * non-zero else xoshiro128starstar will generate only zeroes, and the - * first result needs to be non-zero as expected by random_test.c + * A fixed stream of numbers helps with problem reproduction when + * fuzzing. The first result needs to be non-zero as expected by + * random_test.c (it starts with ISC_RANDOM_BUFSIZE, see above). */ - seed[0] = 1; + return (uint32_t)(isc__random_pos++); #endif /* if FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */ - while (seed[0] == 0 && seed[1] == 0 && seed[2] == 0 && seed[3] == 0) { - isc_entropy_get(seed, sizeof(seed)); + if (isc__random_pos == ISC_RANDOM_BUFSIZE) { + isc_random_buf(isc__random_pool, sizeof(isc__random_pool)); + isc__random_pos = 0; } - initialized = true; -} - -uint8_t -isc_random8(void) { - isc__random_initialize(); - return (uint8_t)next(); -} - -uint16_t -isc_random16(void) { - isc__random_initialize(); - return (uint16_t)next(); -} -uint32_t -isc_random32(void) { - isc__random_initialize(); - return next(); + return isc__random_pool[isc__random_pos++]; } void isc_random_buf(void *buf, size_t buflen) { - REQUIRE(buf != NULL); - REQUIRE(buflen > 0); - - int i; - uint32_t r; - - isc__random_initialize(); + REQUIRE(buflen == 0 || buf != NULL); - for (i = 0; i + sizeof(r) <= buflen; i += sizeof(r)) { - r = next(); - memmove((uint8_t *)buf + i, &r, sizeof(r)); + if (buf == NULL || buflen == 0) { + return; } - r = next(); - memmove((uint8_t *)buf + i, &r, buflen % sizeof(r)); - return; + + int r = uv_random(NULL, NULL, buf, buflen, 0, NULL); + UV_RUNTIME_CHECK(uv_random, r); } uint32_t isc_random_uniform(uint32_t limit) { - isc__random_initialize(); - /* * Daniel Lemire's nearly-divisionless unbiased bounded random numbers. * @@ -161,7 +90,7 @@ isc_random_uniform(uint32_t limit) { * integer part (upper 32 bits), and we will use the fraction part * (lower 32 bits) to determine whether or not we need to resample. */ - uint64_t num = (uint64_t)next() * (uint64_t)limit; + uint64_t num = (uint64_t)isc_random32() * (uint64_t)limit; /* * In the fast path, we avoid doing a division in most cases by * comparing the fraction part of `num` with the limit, which is @@ -213,7 +142,7 @@ isc_random_uniform(uint32_t limit) { * our valid range, it is superfluous, and we resample. */ while ((uint32_t)(num) < residue) { - num = (uint64_t)next() * (uint64_t)limit; + num = (uint64_t)isc_random32() * (uint64_t)limit; } } /* @@ -221,3 +150,5 @@ isc_random_uniform(uint32_t limit) { */ return (uint32_t)(num >> 32); } + +#endif /* HAVE_ARC4RANDOM && !defined(__linux__) */ diff --git a/meson.build b/meson.build index 746e2f1d5f8..98b785b985b 100644 --- a/meson.build +++ b/meson.build @@ -514,6 +514,9 @@ foreach fn, header : { 'sched_getaffinity': '#include ', 'sched_yield': '#include ', + # CSPRNG + 'arc4random': '#include ', + # Misc. 'clock_gettime': '#include ', 'sysctlbyname': '#include ', diff --git a/tests/isc/random_test.c b/tests/isc/random_test.c index 70bd4b6a79e..a8cce6ceca3 100644 --- a/tests/isc/random_test.c +++ b/tests/isc/random_test.c @@ -321,7 +321,9 @@ random_test(pvalue_func_t *func, isc_random_func test_func) { } break; case ISC_RANDOM_BYTES: - isc_random_buf(values, sizeof(values)); + for (i = 0; i < ARRAY_SIZE(values); i++) { + values[i] = isc_random32(); + } break; case ISC_RANDOM_UNIFORM: uniform_values = (uint16_t *)values;