Browse Source

random: Add fallback if getrandom syscall not available

If the code was compiled with newer (>=3.17) kernel headers but executed
on a system without the system call, every use of random would crash the
program. Add a fallback for that case.
0.15
Wladimir J. van der Laan 8 years ago
parent
commit
7e6dcd9995
  1. 49
      src/random.cpp

49
src/random.cpp

@ -102,6 +102,28 @@ static void RandAddSeedPerfmon()
#endif #endif
} }
#ifndef WIN32
/** Fallback: get 32 bytes of system entropy from /dev/urandom. The most
* compatible way to get cryptographic randomness on UNIX-ish platforms.
*/
void GetDevURandom(unsigned char *ent32)
{
int f = open("/dev/urandom", O_RDONLY);
if (f == -1) {
RandFailure();
}
int have = 0;
do {
ssize_t n = read(f, ent32 + have, NUM_OS_RANDOM_BYTES - have);
if (n <= 0 || n + have > NUM_OS_RANDOM_BYTES) {
RandFailure();
}
have += n;
} while (have < NUM_OS_RANDOM_BYTES);
close(f);
}
#endif
/** Get 32 bytes of system entropy. */ /** Get 32 bytes of system entropy. */
void GetOSRand(unsigned char *ent32) void GetOSRand(unsigned char *ent32)
{ {
@ -122,8 +144,17 @@ void GetOSRand(unsigned char *ent32)
* will always return as many bytes as requested and will not be * will always return as many bytes as requested and will not be
* interrupted by signals." * interrupted by signals."
*/ */
if (syscall(SYS_getrandom, ent32, NUM_OS_RANDOM_BYTES, 0) != NUM_OS_RANDOM_BYTES) { int rv = syscall(SYS_getrandom, ent32, NUM_OS_RANDOM_BYTES, 0);
RandFailure(); if (rv != NUM_OS_RANDOM_BYTES) {
if (rv < 0 && errno == ENOSYS) {
/* Fallback for kernel <3.17: the return value will be -1 and errno
* ENOSYS if the syscall is not available, in that case fall back
* to /dev/urandom.
*/
GetDevURandom(ent32);
} else {
RandFailure();
}
} }
#elif defined(HAVE_GETENTROPY) #elif defined(HAVE_GETENTROPY)
/* On OpenBSD this can return up to 256 bytes of entropy, will return an /* On OpenBSD this can return up to 256 bytes of entropy, will return an
@ -150,19 +181,7 @@ void GetOSRand(unsigned char *ent32)
/* Fall back to /dev/urandom if there is no specific method implemented to /* Fall back to /dev/urandom if there is no specific method implemented to
* get system entropy for this OS. * get system entropy for this OS.
*/ */
int f = open("/dev/urandom", O_RDONLY); GetDevURandom(ent32);
if (f == -1) {
RandFailure();
}
int have = 0;
do {
ssize_t n = read(f, ent32 + have, NUM_OS_RANDOM_BYTES - have);
if (n <= 0 || n + have > NUM_OS_RANDOM_BYTES) {
RandFailure();
}
have += n;
} while (have < NUM_OS_RANDOM_BYTES);
close(f);
#endif #endif
} }

Loading…
Cancel
Save