ggentropy.cc (1235B)
1 #include "intrinsics.h" 2 #include "log.h" 3 #include "platform.h" 4 5 #if PLATFORM_LINUX || PLATFORM_OSX 6 7 static bool try_urandom( void * buf, size_t n ) { 8 ASSERT( n <= 256 ); 9 10 FILE * f = fopen( "/dev/urandom", "r" ); 11 if( f == NULL ) 12 return false; 13 14 size_t ok = fread( buf, 1, n, f ); 15 fclose( f ); 16 17 return ok == n; 18 } 19 20 #endif 21 22 #if PLATFORM_WINDOWS 23 24 #include <wincrypt.h> 25 26 bool ggentropy( void * buf, size_t n ) { 27 ASSERT( n <= 256 ); 28 29 HCRYPTPROV provider; 30 if( CryptAcquireContext( &provider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT ) == 0 ) 31 return false; 32 33 int ok = CryptGenRandom( provider, n, ( BYTE * ) buf ); 34 CryptReleaseContext( provider, 0 ); 35 36 return ok != 0; 37 } 38 39 #elif PLATFORM_LINUX 40 41 #include <sys/random.h> 42 43 bool ggentropy( void * buf, size_t n ) { 44 ASSERT( n <= 256 ); 45 46 ssize_t ok = getrandom( buf, n, 0 ); 47 if( ok >= 0 && size_t( ok ) == n ) 48 return true; 49 50 if( errno != ENOSYS ) 51 return false; 52 53 return try_urandom( buf, n ); 54 } 55 56 #elif PLATFORM_OSX 57 58 bool ggentropy( void * buf, size_t n ) { 59 ASSERT( n <= 256 ); 60 return try_urandom( buf, n ); 61 } 62 63 #elif PLATFORM_OPENBSD 64 65 bool ggentropy( void * buf, size_t n ) { 66 ASSERT( n <= 256 ); 67 arc4random_buf( buf, n ); 68 return true; 69 } 70 71 #else 72 #error new platform 73 #endif