prng: support getrandom & getentropy
If the C library supports these random functions, use them directly instead of reading the /dev/urandom file. This makes life easier on platforms that don't have /dev/urandom (like WASM).
This commit is contained in:
committed by
Alex Chernyakhovsky
parent
8e472066be
commit
b5775df441
@@ -272,6 +272,7 @@ AC_CHECK_HEADERS(m4_normalize([
|
||||
stdlib.h
|
||||
string.h
|
||||
sys/ioctl.h
|
||||
sys/random.h
|
||||
sys/resource.h
|
||||
sys/socket.h
|
||||
sys/stat.h
|
||||
@@ -304,6 +305,8 @@ AC_TYPE_UINTPTR_T
|
||||
|
||||
# Checks for library functions.
|
||||
AC_CHECK_FUNCS(m4_normalize([
|
||||
getentropy
|
||||
getrandom
|
||||
gettimeofday
|
||||
posix_memalign
|
||||
cfmakeraw
|
||||
|
||||
+40
-1
@@ -33,6 +33,20 @@
|
||||
#ifndef PRNG_HPP
|
||||
#define PRNG_HPP
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#if !defined( HAVE_GETENTROPY ) && !defined( HAVE_GETRANDOM )
|
||||
#define HAVE_URANDOM 1
|
||||
#else
|
||||
#undef HAVE_URANDOM
|
||||
#endif
|
||||
|
||||
#include <unistd.h>
|
||||
#ifdef HAVE_SYS_RANDOM_H
|
||||
#include <sys/random.h>
|
||||
#endif
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
@@ -43,21 +57,29 @@
|
||||
|
||||
We rely on stdio buffering for efficiency. */
|
||||
|
||||
#ifdef HAVE_URANDOM
|
||||
static const char rdev[] = "/dev/urandom";
|
||||
#endif
|
||||
|
||||
using namespace Crypto;
|
||||
|
||||
class PRNG
|
||||
{
|
||||
private:
|
||||
#ifdef HAVE_URANDOM
|
||||
std::ifstream randfile;
|
||||
#endif
|
||||
|
||||
/* unimplemented to satisfy -Weffc++ */
|
||||
PRNG( const PRNG& );
|
||||
PRNG& operator=( const PRNG& );
|
||||
|
||||
public:
|
||||
PRNG() : randfile( rdev, std::ifstream::in | std::ifstream::binary ) {}
|
||||
PRNG()
|
||||
#ifdef HAVE_URANDOM
|
||||
: randfile( rdev, std::ifstream::in | std::ifstream::binary )
|
||||
#endif
|
||||
{}
|
||||
|
||||
void fill( void* dest, size_t size )
|
||||
{
|
||||
@@ -65,10 +87,27 @@ public:
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined( HAVE_GETRANDOM )
|
||||
if ( getrandom( dest, size, 0 ) != static_cast<ssize_t>( size ) ) {
|
||||
throw CryptoException( "getrandom fell short" );
|
||||
}
|
||||
#elif defined( HAVE_GETENTROPY )
|
||||
// getentropy() can only read up to 256 bytes at a time :(.
|
||||
const size_t max_read = 256;
|
||||
while ( size ) {
|
||||
size_t this_size = std::min( max_read, size );
|
||||
if ( getentropy( dest, this_size ) ) {
|
||||
throw CryptoException( "getentropy fell short" );
|
||||
}
|
||||
size -= this_size;
|
||||
dest = static_cast<char*>( dest ) + this_size;
|
||||
}
|
||||
#else
|
||||
randfile.read( static_cast<char*>( dest ), size );
|
||||
if ( !randfile ) {
|
||||
throw CryptoException( "Could not read from " + std::string( rdev ) );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
uint8_t uint8()
|
||||
|
||||
Reference in New Issue
Block a user