ggentropy

A string formatting library for C++
Log | Files | Refs | README

commit 32fce58a6569d641143503f996b8c98c9956c4d2
Author: Michael Savage <mikejsavage@gmail.com>
Date:   Sat, 28 Dec 2019 12:41:26 +0200

Initial commit

Diffstat:
AREADME.md | 60++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aggentropy.cpp | 108+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aggentropy.h | 23+++++++++++++++++++++++
3 files changed, 191 insertions(+), 0 deletions(-)

diff --git a/README.md b/README.md @@ -0,0 +1,60 @@ +# ggentropy + +ggentropy is a liberally licensed, cross platform, entropy library for +C++. You can use it to generate cryptographically secure random numbers, +safe for use as nonces and keys in cryptographic operations. + +ggentropy supports Windows, MacOS, Linux and OpenBSD. + + +## Usage + +ggentropy has one function: + +```cpp +bool ggentropy( void * buf, size_t n ); +``` + +which writes `n` bytes of crytographically secure random data to `buf`. +It returns true on success and false on failure. Some platforms place a +length restriction on `n`, so the library will exit on all platforms if +`n` is greater than 256. + +Basic usage looks like this: + +```cpp +#include <stdio.h> +#include <stdint.h> +#include <inttypes.h> +#include "ggentropy.h" + +int main() { + uint8_t entropy[ 16 ]; + if( !ggentropy( entropy, sizeof( entropy ) ) ) + return 1; + + for( size_t i = 0; i < sizeof( entropy ); i++ ) { + printf( "%02" PRIx8, entropy[ i ] ); + } + printf( "\n" ); + + return 0; +} +``` + +`ggentropy` can fail. In long lived programs you should use it to seed a +userspace cryptographically secure psuedo-random number generator once +at program startup and use that for all future cryptographically secure +random data. For example, you can encrypt a stream of zeroes using a key +chosen by ggentropy, and use the output of the cipher as a random number +source. + + +## Implementation details + +ggentropy uses the following functionality: + +- Windows: [CryptGenRandom](https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryptgenrandom) +- MacOS: /dev/urandom +- Linux: getrandom with a fallback to /dev/urandom +- OpenBSD: arc4random_buf diff --git a/ggentropy.cpp b/ggentropy.cpp @@ -0,0 +1,108 @@ +/* + * ggentropy + * + * Copyright (c) 2019 Michael Savage <mike@mikejsavage.co.uk> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#if defined( _WIN32 ) +# define PLATFORM_WINDOWS 1 +#elif defined( __linux__ ) +# define PLATFORM_LINUX 1 +#elif defined( __APPLE__ ) +# define PLATFORM_MACOS 1 +#elif defined( __OpenBSD__ ) +# define PLATFORM_OPENBSD 1 +#else +# error new platform +#endif + +#include <assert.h> + +#if PLATFORM_LINUX || PLATFORM_MACOS + +#include <stdio.h> + +static bool try_urandom( void * buf, size_t n ) { + assert( n <= 256 ); + + FILE * f = fopen( "/dev/urandom", "r" ); + if( f == NULL ) + return false; + + size_t ok = fread( buf, 1, n, f ); + fclose( f ); + + return ok == n; +} + +#endif + +#if PLATFORM_WINDOWS + +#include <windows.h> +#include <wincrypt.h> + +bool ggentropy( void * buf, size_t n ) { + assert( n <= 256 ); + + HCRYPTPROV provider; + if( CryptAcquireContext( &provider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT ) == 0 ) + return false; + + int ok = CryptGenRandom( provider, n, ( BYTE * ) buf ); + CryptReleaseContext( provider, 0 ); + + return ok != 0; +} + +#elif PLATFORM_LINUX + +#include <errno.h> +#include <unistd.h> +#include <sys/syscall.h> + +bool ggentropy( void * buf, size_t n ) { + assert( n <= 256 ); + + int ok = syscall( SYS_getrandom, buf, n, 0 ); + if( ok >= 0 && size_t( ok ) == n ) + return true; + + if( errno != ENOSYS ) + return false; + + return try_urandom( buf, n ); +} + +#elif PLATFORM_MACOS + +bool ggentropy( void * buf, size_t n ) { + assert( n <= 256 ); + return try_urandom( buf, n ); +} + +#elif PLATFORM_OPENBSD + +#include <stdlib.h> + +bool ggentropy( void * buf, size_t n ) { + assert( n <= 256 ); + arc4random_buf( buf, n ); + return true; +} + +#else +#error new platform +#endif diff --git a/ggentropy.h b/ggentropy.h @@ -0,0 +1,23 @@ +/* + * ggentropy + * + * Copyright (c) 2019 Michael Savage <mike@mikejsavage.co.uk> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#pragma once + +#include <stddef.h> + +bool ggentropy( void * buf, size_t n );