static int arc4_seed_sysctl_linux(void) { /* Based on code by William Ahern, this function tries to use the * RANDOM_UUID sysctl to get entropy from the kernel. This can work * even if /dev/urandom is inaccessible for some reason (e.g., we're * running in a chroot). */ int mib[] = { CTL_KERN, KERN_RANDOM, RANDOM_UUID }; unsigned char buf[ADD_ENTROPY]; size_t len, n; unsigned i; int any_set; memset(buf, 0, sizeof(buf)); for (len = 0; len < sizeof(buf); len += n) { n = sizeof(buf) - len; if (0 != sysctl(mib, 3, &buf[len], &n, NULL, 0)) return -1; } /* make sure that the buffer actually got set. */ for (i=0,any_set=0; i<sizeof(buf); ++i) { any_set |= buf[i]; } if (!any_set) return -1; arc4_addrandom(buf, sizeof(buf)); evutil_memclear_(buf, sizeof(buf)); arc4_seeded_ok = 1; return 0; }
static int arc4_seed_sysctl_bsd(void) { /* Based on code from William Ahern and from OpenBSD, this function * tries to use the KERN_ARND syscall to get entropy from the kernel. * This can work even if /dev/urandom is inaccessible for some reason * (e.g., we're running in a chroot). */ int mib[] = { CTL_KERN, KERN_ARND }; unsigned char buf[ADD_ENTROPY]; size_t len, n; int i, any_set; memset(buf, 0, sizeof(buf)); len = sizeof(buf); if (sysctl(mib, 2, buf, &len, NULL, 0) == -1) { for (len = 0; len < sizeof(buf); len += sizeof(unsigned)) { n = sizeof(unsigned); if (n + len > sizeof(buf)) n = len - sizeof(buf); if (sysctl(mib, 2, &buf[len], &n, NULL, 0) == -1) return -1; } } /* make sure that the buffer actually got set. */ for (i=any_set=0; i<sizeof(buf); ++i) { any_set |= buf[i]; } if (!any_set) return -1; arc4_addrandom(buf, sizeof(buf)); evutil_memclear_(buf, sizeof(buf)); return 0; }
static int arc4_seed_proc_sys_kernel_random_uuid(void) { /* Occasionally, somebody will make /proc/sys accessible in a chroot, * but not /dev/urandom. Let's try /proc/sys/kernel/random/uuid. * Its format is stupid, so we need to decode it from hex. */ int fd; char buf[128]; unsigned char entropy[64]; int bytes, n, i, nybbles; for (bytes = 0; bytes<ADD_ENTROPY; ) { fd = evutil_open_closeonexec_("/proc/sys/kernel/random/uuid", O_RDONLY, 0); if (fd < 0) return -1; n = read(fd, buf, sizeof(buf)); close(fd); if (n<=0) return -1; memset(entropy, 0, sizeof(entropy)); for (i=nybbles=0; i<n; ++i) { if (EVUTIL_ISXDIGIT_(buf[i])) { int nyb = evutil_hex_char_to_int_(buf[i]); if (nybbles & 1) { entropy[nybbles/2] |= nyb; } else { entropy[nybbles/2] |= nyb<<4; } ++nybbles; } } if (nybbles < 2) return -1; arc4_addrandom(entropy, nybbles/2); bytes += nybbles/2; } evutil_memclear_(entropy, sizeof(entropy)); evutil_memclear_(buf, sizeof(buf)); arc4_seeded_ok = 1; return 0; }
static int arc4_seed_urandom_helper_(const char *fname) { unsigned char buf[ADD_ENTROPY]; int fd; size_t n; fd = evutil_open_closeonexec_(fname, O_RDONLY, 0); if (fd<0) return -1; n = read_all(fd, buf, sizeof(buf)); close(fd); if (n != sizeof(buf)) return -1; arc4_addrandom(buf, sizeof(buf)); evutil_memclear_(buf, sizeof(buf)); return 0; }
static int arc4_seed_win32(void) { /* This is adapted from Tor's crypto_seed_rng() */ unsigned char buf[ADD_ENTROPY]={0}; #if 0 static int provider_set = 0; static HCRYPTPROV provider; if (!provider_set) { if (!CryptAcquireContext(&provider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { if (GetLastError() != (DWORD)NTE_BAD_KEYSET) return -1; } provider_set = 1; } if (!CryptGenRandom(provider, sizeof(buf), buf)) return -1; #else int irend=0; int count=ADD_ENTROPY/4; srand((int)time(0)); while(count>0) { count--; irend=rand(); memcpy(buf+count*4,&irend,4); } #endif arc4_addrandom(buf, sizeof(buf)); evutil_memclear_(buf, sizeof(buf)); arc4_seeded_ok = 1; return 0; return -1; }
static int arc4_seed_win32(void) { /* This is adapted from Tor's crypto_seed_rng() */ static int provider_set = 0; static HCRYPTPROV provider; unsigned char buf[ADD_ENTROPY]; if (!provider_set) { if (!CryptAcquireContext(&provider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { if (GetLastError() != (DWORD)NTE_BAD_KEYSET) return -1; } provider_set = 1; } if (!CryptGenRandom(provider, sizeof(buf), buf)) return -1; arc4_addrandom(buf, sizeof(buf)); evutil_memclear_(buf, sizeof(buf)); return 0; }