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
|
stdlib.h
|
||||||
string.h
|
string.h
|
||||||
sys/ioctl.h
|
sys/ioctl.h
|
||||||
|
sys/random.h
|
||||||
sys/resource.h
|
sys/resource.h
|
||||||
sys/socket.h
|
sys/socket.h
|
||||||
sys/stat.h
|
sys/stat.h
|
||||||
@@ -304,6 +305,8 @@ AC_TYPE_UINTPTR_T
|
|||||||
|
|
||||||
# Checks for library functions.
|
# Checks for library functions.
|
||||||
AC_CHECK_FUNCS(m4_normalize([
|
AC_CHECK_FUNCS(m4_normalize([
|
||||||
|
getentropy
|
||||||
|
getrandom
|
||||||
gettimeofday
|
gettimeofday
|
||||||
posix_memalign
|
posix_memalign
|
||||||
cfmakeraw
|
cfmakeraw
|
||||||
|
|||||||
+40
-1
@@ -33,6 +33,20 @@
|
|||||||
#ifndef PRNG_HPP
|
#ifndef PRNG_HPP
|
||||||
#define 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 <cstdint>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -43,21 +57,29 @@
|
|||||||
|
|
||||||
We rely on stdio buffering for efficiency. */
|
We rely on stdio buffering for efficiency. */
|
||||||
|
|
||||||
|
#ifdef HAVE_URANDOM
|
||||||
static const char rdev[] = "/dev/urandom";
|
static const char rdev[] = "/dev/urandom";
|
||||||
|
#endif
|
||||||
|
|
||||||
using namespace Crypto;
|
using namespace Crypto;
|
||||||
|
|
||||||
class PRNG
|
class PRNG
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
#ifdef HAVE_URANDOM
|
||||||
std::ifstream randfile;
|
std::ifstream randfile;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* unimplemented to satisfy -Weffc++ */
|
/* unimplemented to satisfy -Weffc++ */
|
||||||
PRNG( const PRNG& );
|
PRNG( const PRNG& );
|
||||||
PRNG& operator=( const PRNG& );
|
PRNG& operator=( const PRNG& );
|
||||||
|
|
||||||
public:
|
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 )
|
void fill( void* dest, size_t size )
|
||||||
{
|
{
|
||||||
@@ -65,10 +87,27 @@ public:
|
|||||||
return;
|
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 );
|
randfile.read( static_cast<char*>( dest ), size );
|
||||||
if ( !randfile ) {
|
if ( !randfile ) {
|
||||||
throw CryptoException( "Could not read from " + std::string( rdev ) );
|
throw CryptoException( "Could not read from " + std::string( rdev ) );
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t uint8()
|
uint8_t uint8()
|
||||||
|
|||||||
Reference in New Issue
Block a user