#include #include "grv.h" #ifdef __unix__ #include #include #include #include static int xread(int fd, void *buf, size_t count) { char *b = (char *)buf; int n = 0; int rv; while ( count ) { rv = read(fd, b, count); if ( rv == -1 ) { if ( errno == EINTR || errno == EAGAIN ) continue; else return n ? n : -1; } else if ( rv == 0 ) { return n; } count -= rv; n += rv; b += rv; } return n; } static int randfd = -1; int get_random_bytes(void *ptr, int len) { /* We might have /dev/urandom */ if (randfd < 0) { randfd = open("/dev/urandom", O_RDONLY); if (randfd < 0) return -1; /* * File descriptors are closed automatically on process exit, so * we don't bother setting up atexit() here. */ } return xread(randfd, ptr, len) == len ? 0 : -1; } #elif defined(__WIN32__) #include #include static HCRYPTPROV hProv; static int provider_open = 0; static void close_provider(void) { CryptReleaseContext(hProv, 0); provider_open = 0; } int get_random_bytes(void *ptr, int len) { BOOL ok; static const DWORD providers[] = { PROV_RNG, PROV_INTEL_SEC, PROV_RSA_SIG, PROV_RSA_FULL, PROV_DSS, PROV_SSL, 0 }; if (!provider_open) { const DWORD *pp = providers; while (*pp) { if (CryptAcquireContext(&hProv, NULL, NULL, *pp, CRYPT_SILENT | CRYPT_VERIFYCONTEXT)) goto found; pp++; } return -1; /* No provider available */ found: provider_open = 1; atexit(close_provider); } ok = CryptGenRandom(hProv, len, ptr); return ok ? 0 : -1; } #else /* Need system-specific code here */ int get_random_bytes(void *ptr, int len) { return -1; } #endif void randomize(void) { unsigned long key_array[32/sizeof(unsigned long)]; key_array[0] = time(0); /* Better than nothing on failure*/ get_random_bytes(key_array, sizeof key_array); init_by_array(key_array, sizeof key_array/(sizeof key_array[0])); }