summaryrefslogtreecommitdiffstats
path: root/utils/lib/randutils.c
diff options
context:
space:
mode:
Diffstat (limited to 'utils/lib/randutils.c')
-rw-r--r--utils/lib/randutils.c238
1 files changed, 0 insertions, 238 deletions
diff --git a/utils/lib/randutils.c b/utils/lib/randutils.c
deleted file mode 100644
index bd2a8f6..0000000
--- a/utils/lib/randutils.c
+++ /dev/null
@@ -1,238 +0,0 @@
-/*
- * SPDX-License-Identifier: BSD-3-Clause
- *
- * General purpose random utilities. Based on libuuid code.
- *
- * This code is free software; you can redistribute it and/or modify it under
- * the terms of the Modified BSD License. The complete text of the license is
- * available in the Documentation/licenses/COPYING.BSD-3-Clause file.
- */
-#include <stdio.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/time.h>
-
-#include <sys/syscall.h>
-
-#include "c.h"
-#include "randutils.h"
-#include "nls.h"
-
-#ifdef HAVE_TLS
-#define THREAD_LOCAL static __thread
-#else
-#define THREAD_LOCAL static
-#endif
-
-#ifdef HAVE_GETRANDOM
-# include <sys/random.h>
-#elif defined (__linux__)
-# if !defined(SYS_getrandom) && defined(__NR_getrandom)
- /* usable kernel-headers, but old glibc-headers */
-# define SYS_getrandom __NR_getrandom
-# endif
-#endif
-
-#if !defined(HAVE_GETRANDOM) && defined(SYS_getrandom)
-/* libc without function, but we have syscal */
-#define GRND_NONBLOCK 0x01
-#define GRND_RANDOM 0x02
-static int getrandom(void *buf, size_t buflen, unsigned int flags)
-{
- return (syscall(SYS_getrandom, buf, buflen, flags));
-}
-# define HAVE_GETRANDOM
-#endif
-
-#if defined(__linux__) && defined(__NR_gettid) && defined(HAVE_JRAND48)
-#define DO_JRAND_MIX
-THREAD_LOCAL unsigned short ul_jrand_seed[3];
-#endif
-
-int rand_get_number(int low_n, int high_n)
-{
- return rand() % (high_n - low_n + 1) + low_n;
-}
-
-static void crank_random(void)
-{
- int i;
- struct timeval tv;
- unsigned int n_pid, n_uid;
-
- gettimeofday(&tv, NULL);
- n_pid = getpid();
- n_uid = getuid();
- srand((n_pid << 16) ^ n_uid ^ tv.tv_sec ^ tv.tv_usec);
-
-#ifdef DO_JRAND_MIX
- ul_jrand_seed[0] = getpid() ^ (tv.tv_sec & 0xFFFF);
- ul_jrand_seed[1] = getppid() ^ (tv.tv_usec & 0xFFFF);
- ul_jrand_seed[2] = (tv.tv_sec ^ tv.tv_usec) >> 16;
-#endif
- /* Crank the random number generator a few times */
- gettimeofday(&tv, NULL);
- for (i = (tv.tv_sec ^ tv.tv_usec) & 0x1F; i > 0; i--)
- rand();
-}
-
-int random_get_fd(void)
-{
- int i, fd;
-
- fd = open("/dev/urandom", O_RDONLY | O_CLOEXEC);
- if (fd == -1)
- fd = open("/dev/random", O_RDONLY | O_NONBLOCK | O_CLOEXEC);
- if (fd >= 0) {
- i = fcntl(fd, F_GETFD);
- if (i >= 0)
- fcntl(fd, F_SETFD, i | FD_CLOEXEC);
- }
- crank_random();
- return fd;
-}
-
-/*
- * Generate a stream of random nbytes into buf.
- * Use /dev/urandom if possible, and if not,
- * use glibc pseudo-random functions.
- */
-#define UL_RAND_READ_ATTEMPTS 8
-#define UL_RAND_READ_DELAY 125000 /* microseconds */
-
-void random_get_bytes(void *buf, size_t nbytes)
-{
- unsigned char *cp = (unsigned char *)buf;
- size_t i, n = nbytes;
- int lose_counter = 0;
-
-#ifdef HAVE_GETRANDOM
- while (n > 0) {
- int x;
-
- errno = 0;
- x = getrandom(cp, n, GRND_NONBLOCK);
- if (x > 0) { /* success */
- n -= x;
- cp += x;
- lose_counter = 0;
-
- } else if (errno == ENOSYS) { /* kernel without getrandom() */
- break;
-
- } else if (errno == EAGAIN && lose_counter < UL_RAND_READ_ATTEMPTS) {
- xusleep(UL_RAND_READ_DELAY); /* no entropy, wait and try again */
- lose_counter++;
- } else
- break;
- }
-
- if (errno == ENOSYS)
-#endif
- /*
- * We've been built against headers that support getrandom, but the
- * running kernel does not. Fallback to reading from /dev/{u,}random
- * as before
- */
- {
- int fd = random_get_fd();
-
- lose_counter = 0;
- if (fd >= 0) {
- while (n > 0) {
- ssize_t x = read(fd, cp, n);
- if (x <= 0) {
- if (lose_counter++ > UL_RAND_READ_ATTEMPTS)
- break;
- xusleep(UL_RAND_READ_DELAY);
- continue;
- }
- n -= x;
- cp += x;
- lose_counter = 0;
- }
-
- close(fd);
- }
- }
- /*
- * We do this all the time, but this is the only source of
- * randomness if /dev/random/urandom is out to lunch.
- */
- crank_random();
- for (cp = buf, i = 0; i < nbytes; i++)
- *cp++ ^= (rand() >> 7) & 0xFF;
-
-#ifdef DO_JRAND_MIX
- {
- unsigned short tmp_seed[3];
-
- memcpy(tmp_seed, ul_jrand_seed, sizeof(tmp_seed));
- ul_jrand_seed[2] = ul_jrand_seed[2] ^ syscall(__NR_gettid);
- for (cp = buf, i = 0; i < nbytes; i++)
- *cp++ ^= (jrand48(tmp_seed) >> 7) & 0xFF;
- memcpy(ul_jrand_seed, tmp_seed,
- sizeof(ul_jrand_seed)-sizeof(unsigned short));
- }
-#endif
-}
-
-
-/*
- * Tell source of randomness.
- */
-const char *random_tell_source(void)
-{
-#ifdef HAVE_GETRANDOM
- return _("getrandom() function");
-#else
- size_t i;
- static const char *random_sources[] = {
- "/dev/urandom",
- "/dev/random"
- };
-
- for (i = 0; i < ARRAY_SIZE(random_sources); i++) {
- if (!access(random_sources[i], R_OK))
- return random_sources[i];
- }
-#endif
- return _("libc pseudo-random functions");
-}
-
-#ifdef TEST_PROGRAM_RANDUTILS
-#include <inttypes.h>
-
-int main(int argc, char *argv[])
-{
- size_t i, n;
- int64_t *vp, v;
- char *buf;
- size_t bufsz;
-
- n = argc == 1 ? 16 : atoi(argv[1]);
-
- printf("Multiple random calls:\n");
- for (i = 0; i < n; i++) {
- random_get_bytes(&v, sizeof(v));
- printf("#%02zu: %25"PRIu64"\n", i, v);
- }
-
-
- printf("One random call:\n");
- bufsz = n * sizeof(*vp);
- buf = malloc(bufsz);
- if (!buf)
- err(EXIT_FAILURE, "failed to allocate buffer");
-
- random_get_bytes(buf, bufsz);
- for (i = 0; i < n; i++) {
- vp = (int64_t *) (buf + (i * sizeof(*vp)));
- printf("#%02zu: %25"PRIu64"\n", i, *vp);
- }
-
- return EXIT_SUCCESS;
-}
-#endif /* TEST_PROGRAM_RANDUTILS */