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 <isc/entropy.h>
-#include <isc/types.h>
-#include <isc/util.h>
-#include <isc/uv.h>
-
-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 <stddef.h>
 
 #include <isc/ascii.h>
-#include <isc/entropy.h>
 #include <isc/hash.h> /* IWYU pragma: keep */
 #include <isc/random.h>
 #include <isc/result.h>
@@ -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 <isc/ascii.h>
 #include <isc/atomic.h>
-#include <isc/entropy.h>
 #include <isc/hash.h>
 #include <isc/hashmap.h>
 #include <isc/magic.h>
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 <stdlib.h>
-
-/*! \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 <stdlib.h>
 
+#include <isc/random.h>
+
 /*! \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 <isc/types.h>
 
 /*! \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 <isc/entropy.h>
-#include <isc/nonce.h>
-
-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 <inttypes.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
+#include <stdio.h>
 
-#include <isc/entropy.h>
+#include <isc/os.h>
 #include <isc/random.h>
-#include <isc/result.h>
 #include <isc/thread.h>
-#include <isc/types.h>
 #include <isc/util.h>
+#include <isc/uv.h>
 
-/*
- * 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 <http://creativecommons.org/publicdomain/zero/1.0/>.
- */
-
-/*
- * 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.h>',
     'sched_yield': '#include <sched.h>',
 
+    # CSPRNG
+    'arc4random': '#include <stdlib.h>',
+
     # Misc.
     'clock_gettime': '#include <time.h>',
     'sysctlbyname': '#include <sys/sysctl.h>',
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;
