TEST(sys_random, getentropy) { #if defined(HAVE_SYS_RANDOM) char buf1[64]; char buf2[64]; ASSERT_EQ(0, getentropy(buf1, sizeof(buf1))); ASSERT_EQ(0, getentropy(buf2, sizeof(buf2))); ASSERT_TRUE(memcmp(buf1, buf2, sizeof(buf1)) != 0); #else GTEST_SKIP() << "<sys/random.h> not available"; #endif }
TEST(sys_random, getentropy) { #if defined(HAVE_SYS_RANDOM) char buf1[64]; char buf2[64]; ASSERT_EQ(0, getentropy(buf1, sizeof(buf1))); ASSERT_EQ(0, getentropy(buf2, sizeof(buf2))); ASSERT_TRUE(memcmp(buf1, buf2, sizeof(buf1)) != 0); #else GTEST_LOG_(INFO) << "This test requires a C library with <sys/random.h>.\n"; #endif }
static int osrandom_rand_bytes(unsigned char *buffer, int size) { int len; int res; switch(getentropy_works) { #if defined(__APPLE__) case CRYPTOGRAPHY_OSRANDOM_GETENTROPY_FALLBACK: return dev_urandom_read(buffer, size); #endif case CRYPTOGRAPHY_OSRANDOM_GETENTROPY_WORKS: while (size > 0) { /* OpenBSD and macOS restrict maximum buffer size to 256. */ len = size > 256 ? 256 : size; res = getentropy(buffer, (size_t)len); if (res < 0) { ERR_Cryptography_OSRandom_error( CRYPTOGRAPHY_OSRANDOM_F_RAND_BYTES, CRYPTOGRAPHY_OSRANDOM_R_GETENTROPY_FAILED, __FILE__, __LINE__ ); return 0; } buffer += len; size -= len; } return 1; } __builtin_unreachable(); }
static int li_getentropy (void *buf, size_t buflen) { #ifdef HAVE_GETENTROPY return getentropy(buf, buflen); #else /*(see NOTES section in 'man getrandom' on Linux)*/ #if defined(HAVE_GETRANDOM) || defined(SYS_getrandom) if (buflen <= 256) { #ifdef HAVE_GETRANDOM /*(not implemented in glibc yet)*/ int num = getrandom(buf, buflen, 0); #elif defined(SYS_getrandom) /* https://lwn.net/Articles/605828/ */ /* https://bbs.archlinux.org/viewtopic.php?id=200039 */ int num = (int)syscall(SYS_getrandom, buf, buflen, 0); #endif if (num == (int)buflen) return 0; if (num < 0) return num; /* -1 */ } #else UNUSED(buf); UNUSED(buflen); #endif errno = EIO; return -1; #endif }
static void _rs_stir(void) { u_char rnd[KEYSZ + IVSZ]; if (getentropy(rnd, sizeof rnd) == -1) { #ifdef SIGKILL raise(SIGKILL); #else exit(9); /* windows */ #endif } if (!rs) _rs_init(rnd, sizeof(rnd)); else _rs_rekey(rnd, sizeof(rnd)); explicit_bzero(rnd, sizeof(rnd)); /* discard source seed */ /* invalidate rs_buf */ rs->rs_have = 0; memset(rsx->rs_buf, 0, sizeof(rsx->rs_buf)); rs->rs_count = 1600000; }
static int get(struct RandomSeed* randomSeed, uint64_t output[8]) { if (getentropy(output, 64) < 0) { return -1; } else { return 0; } }
TEST(sys_random, getentropy_EFAULT) { #if defined(HAVE_SYS_RANDOM) errno = 0; ASSERT_EQ(-1, getentropy(nullptr, 1)); ASSERT_EQ(EFAULT, errno); #else GTEST_SKIP() << "<sys/random.h> not available"; #endif }
TEST(sys_random, getentropy_EFAULT) { #if defined(HAVE_SYS_RANDOM) errno = 0; ASSERT_EQ(-1, getentropy(nullptr, 1)); ASSERT_EQ(EFAULT, errno); #else GTEST_LOG_(INFO) << "This test requires a C library with <sys/random.h>.\n"; #endif }
/* * syscall_random(): Try to get random data using a system call * returns the number of bytes returned in buf, or < 0 on error. */ static ssize_t syscall_random(void *buf, size_t buflen) { /* * Note: 'buflen' equals the size of the buffer which is used by the * get_entropy() callback of the RAND_DRBG. It is roughly bounded by * * 2 * RAND_POOL_FACTOR * (RAND_DRBG_STRENGTH / 8) = 2^14 * * which is way below the OSSL_SSIZE_MAX limit. Therefore sign conversion * between size_t and ssize_t is safe even without a range check. */ /* * Do runtime detection to find getentropy(). * * Known OSs that should support this: * - Darwin since 16 (OSX 10.12, IOS 10.0). * - Solaris since 11.3 * - OpenBSD since 5.6 * - Linux since 3.17 with glibc 2.25 * - FreeBSD since 12.0 (1200061) */ # if defined(__GNUC__) && __GNUC__>=2 && defined(__ELF__) && !defined(__hpux) extern int getentropy(void *buffer, size_t length) __attribute__((weak)); if (getentropy != NULL) return getentropy(buf, buflen) == 0 ? (ssize_t)buflen : -1; # else union { void *p; int (*f)(void *buffer, size_t length); } p_getentropy; /* * We could cache the result of the lookup, but we normally don't * call this function often. */ ERR_set_mark(); p_getentropy.p = DSO_global_lookup("getentropy"); ERR_pop_to_mark(); if (p_getentropy.p != NULL) return p_getentropy.f(buf, buflen) == 0 ? (ssize_t)buflen : -1; # endif /* Linux supports this since version 3.17 */ # if defined(__linux) && defined(SYS_getrandom) return syscall(SYS_getrandom, buf, buflen, 0); # elif (defined(__FreeBSD__) || defined(__NetBSD__)) && defined(KERN_ARND) return sysctl_random(buf, buflen); # else errno = ENOSYS; return -1; # endif }
TEST(sys_random, getentropy_EIO) { #if defined(HAVE_SYS_RANDOM) char buf[BUFSIZ]; static_assert(BUFSIZ > 256, "BUFSIZ <= 256!"); errno = 0; ASSERT_EQ(-1, getentropy(buf, sizeof(buf))); ASSERT_EQ(EIO, errno); #else GTEST_SKIP() << "<sys/random.h> not available"; #endif }
TEST(sys_random, getentropy_EIO) { #if defined(HAVE_SYS_RANDOM) char buf[BUFSIZ]; static_assert(BUFSIZ > 256, "BUFSIZ <= 256!"); errno = 0; ASSERT_EQ(-1, getentropy(buf, sizeof(buf))); ASSERT_EQ(EIO, errno); #else GTEST_LOG_(INFO) << "This test requires a C library with <sys/random.h>.\n"; #endif }
/** Generates a random vector of AUTH_VECTOR_LEN octets * * @param vector a buffer with at least %AUTH_VECTOR_LEN bytes. */ static void rc_random_vector (unsigned char *vector) { int randno; int i; #if defined(HAVE_GETENTROPY) if (getentropy(vector, AUTH_VECTOR_LEN) >= 0) { return; } /* else fall through */ #elif defined(HAVE_DEV_URANDOM) int fd; /* well, I added this to increase the security for user passwords. we use /dev/urandom here, as /dev/random might block and we don't need that much randomness. BTW, great idea, Ted! -lf, 03/18/95 */ if ((fd = open(_PATH_DEV_URANDOM, O_RDONLY)) >= 0) { unsigned char *pos; int readcount; i = AUTH_VECTOR_LEN; pos = vector; while (i > 0) { readcount = read(fd, (char *)pos, i); if (readcount >= 0) { pos += readcount; i -= readcount; } else { if (errno != EINTR && errno != EAGAIN) goto fallback; } } close(fd); return; } /* else fall through */ #endif fallback: for (i = 0; i < AUTH_VECTOR_LEN;) { randno = random (); memcpy ((char *) vector, (char *) &randno, sizeof (int)); vector += sizeof (int); i += sizeof (int); } return; }
/* * syscall_random(): Try to get random data using a system call * returns the number of bytes returned in buf, or <= 0 on error. */ int syscall_random(void *buf, size_t buflen) { /* * Do runtime detection to find getentropy(). * * Known OSs that should support this: * - Darwin since 16 (OSX 10.12, IOS 10.0). * - Solaris since 11.3 * - OpenBSD since 5.6 * - Linux since 3.17 with glibc 2.25 * - FreeBSD since 12.0 (1200061) */ # if defined(__GNUC__) && __GNUC__>=2 && defined(__ELF__) && !defined(__hpux) extern int getentropy(void *bufer, size_t length) __attribute__((weak)); if (getentropy != NULL) return getentropy(buf, buflen) == 0 ? buflen : 0; # else union { void *p; int (*f)(void *buffer, size_t length); } p_getentropy; /* * We could cache the result of the lookup, but we normally don't * call this function often. */ ERR_set_mark(); p_getentropy.p = DSO_global_lookup("getentropy"); ERR_pop_to_mark(); if (p_getentropy.p != NULL) return p_getentropy.f(buf, buflen) == 0 ? buflen : 0; # endif /* Linux supports this since version 3.17 */ # if defined(__linux) && defined(SYS_getrandom) return (int)syscall(SYS_getrandom, buf, buflen, 0); # endif # if (defined(__FreeBSD__) || defined(__NetBSD__)) && defined(KERN_ARND) return (int)sysctl_random(buf, buflen); # endif return -1; }
/* Fill buffer with size pseudo-random bytes generated by getentropy(). Return 0 on success, or raise an exception and return -1 on error. If fatal is nonzero, call Py_FatalError() instead of raising an exception on error. */ static int py_getentropy(unsigned char *buffer, Py_ssize_t size, int fatal) { while (size > 0) { Py_ssize_t len = Py_MIN(size, 256); int res; if (!fatal) { Py_BEGIN_ALLOW_THREADS res = getentropy(buffer, len); Py_END_ALLOW_THREADS if (res < 0) { PyErr_SetFromErrno(PyExc_OSError); return -1; } } else {
static void _rs_stir(void) { u_char rnd[KEYSZ + IVSZ]; if (getentropy(rnd, sizeof rnd) == -1) _getentropy_fail(); if (!rs) _rs_init(rnd, sizeof(rnd)); else _rs_rekey(rnd, sizeof(rnd)); explicit_bzero(rnd, sizeof(rnd)); /* discard source seed */ /* invalidate rs_buf */ rs->rs_have = 0; memset(rsx->rs_buf, 0, sizeof(rsx->rs_buf)); rs->rs_count = 1600000; }
/* Generate pseudorandom data to stdout. Long parameter is kilobytes */ int prandom (long quantity) { char entropy[1024]; char pdata[1024]; int x,y; int xlim = 1024; long kb_rem = quantity; while(kb_rem > 0) { getentropy(entropy); if (kb_rem < 1024) { xlim = kb_rem; } for(x=0; x<xlim; x++) { for(y=0; y<1024; y++) { pdata[y] = entropy[x] ^ entropy[y]; } write(1, pdata, 1024); } kb_rem = kb_rem - 1024; } return 0; }
while (size > 0) { Py_ssize_t len = Py_MIN(size, 256); int res; if (!fatal) { Py_BEGIN_ALLOW_THREADS res = getentropy(buffer, len); Py_END_ALLOW_THREADS if (res < 0) { PyErr_SetFromErrno(PyExc_OSError); return -1; } } else { res = getentropy(buffer, len); if (res < 0) Py_FatalError("getentropy() failed"); } buffer += len; size -= len; } return 0; } #else /* Issue #25003: Don' use getentropy() on Solaris (available since * Solaris 11.3), it is blocking whereas os.urandom() should not block. */ #if defined(HAVE_GETRANDOM) || defined(HAVE_GETRANDOM_SYSCALL)
int my_getentropy(void *buf, size_t buflen){ return getentropy(buf, buflen); }
/** Generate 128 bits of random noise for seeding RNGs. Attempts to * use various OS-specific sources of random bits, with a fallback * based on time and pid. */ void generate_seed(uint64_t seeds[]) { bool seed_generated = false; static int stream_count = 0; int len = sizeof(uint64_t) * 2; #ifdef HAVE_GETENTROPY /* On OpenBSD and up to date Linux, use getentropy() to avoid the open/read/close sequence with /dev/urandom */ if (!seed_generated && getentropy(seeds, len) == 0) { fprintf(stderr, "Seeded RNG with getentropy()\n"); seed_generated = true; } #endif #ifdef HAVE_ARC4RANDOM_BUF /* Most (all?) of the BSDs have this seeder. Use it for the reasons above. Also available on Linux with libbsd, but we don't check for that. */ if (!seed_generated) { arc4random_buf(seeds, len); fprintf(stderr, "Seeded RNG with arc4random\n"); seed_generated = true; } #endif #ifdef WIN32 if (!seed_generated) { /* Use the Win32 bcrypto RNG interface */ if (BCryptGenRandom(NULL, (PUCHAR) seeds, len, BCRYPT_USE_SYSTEM_PREFERRED_RNG) == STATUS_SUCCESS) { fprintf(stderr, "Seeding RNG with BCryptGenRandom()\n"); seed_generated = true; } } #endif #ifdef HAVE_DEV_URANDOM if (!seed_generated) { /* Seed from /dev/urandom if available */ int fd; fd = open("/dev/urandom", O_RDONLY); if (fd >= 0) { int r = read(fd, (void *) seeds, len); close(fd); if (r != len) { fprintf(stderr, "Couldn't read from /dev/urandom! Resorting to normal " "seeding method.\n"); } else { fprintf(stderr, "Seeding RNG with /dev/urandom\n"); seed_generated = true; } } else { fprintf(stderr, "Couldn't open /dev/urandom to seed random number " "generator. Resorting to normal seeding method.\n"); } } #endif if (!seed_generated) { /* Default seeder. Pick a seed that's slightly random */ #ifdef WIN32 seeds[0] = (uint64_t) time(NULL); seeds[1] = (uint64_t) GetCurrentProcessId() + stream_count; #else seeds[0] = (uint64_t) time(NULL); seeds[1] = (uint64_t) getpid() + stream_count; #endif stream_count += 1; } }