handle EAGAIN from /dev/urandom and /dev/random (Folkert van Heusden)

pull/2/head
weidai 2013-01-26 17:31:23 +00:00
parent ed7652256c
commit 280c881393
1 changed files with 25 additions and 4 deletions

View File

@ -83,8 +83,22 @@ void NonblockingRng::GenerateBlock(byte *output, size_t size)
if (!CryptGenRandom(m_Provider.GetProviderHandle(), (DWORD)size, output)) if (!CryptGenRandom(m_Provider.GetProviderHandle(), (DWORD)size, output))
throw OS_RNG_Err("CryptGenRandom"); throw OS_RNG_Err("CryptGenRandom");
#else #else
if (read(m_fd, output, size) != size) while (size)
{
ssize_t len = read(m_fd, output, size);
if (len < 0)
{
// /dev/urandom reads CAN give EAGAIN errors! (maybe EINTR as well)
if (errno != EINTR && errno != EAGAIN)
throw OS_RNG_Err("read /dev/urandom"); throw OS_RNG_Err("read /dev/urandom");
continue;
}
output += len;
size -= len;
}
#endif #endif
} }
@ -119,10 +133,17 @@ void BlockingRng::GenerateBlock(byte *output, size_t size)
while (size) while (size)
{ {
// on some systems /dev/random will block until all bytes // on some systems /dev/random will block until all bytes
// are available, on others it will returns immediately // are available, on others it returns immediately
ssize_t len = read(m_fd, output, size); ssize_t len = read(m_fd, output, size);
if (len < 0) if (len < 0)
{
// /dev/random reads CAN give EAGAIN errors! (maybe EINTR as well)
if (errno != EINTR && errno != EAGAIN)
throw OS_RNG_Err("read " CRYPTOPP_BLOCKING_RNG_FILENAME); throw OS_RNG_Err("read " CRYPTOPP_BLOCKING_RNG_FILENAME);
continue;
}
size -= len; size -= len;
output += len; output += len;
if (size) if (size)