From aa7e4cce8e7208a6128054d1917eba0a749fe1f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C5=8Dshin?= Date: Tue, 25 Dec 2018 19:44:59 -0800 Subject: [PATCH 01/43] Initial --- README.md | 4 ++++ include/ent/detail.h | 26 ++++++++++++++++++++++++++ include/ent/ent.h | 12 ++++++++++++ meson.build | 21 +++++++++++++++++++++ src/ent.c | 17 +++++++++++++++++ 5 files changed, 80 insertions(+) create mode 100644 README.md create mode 100644 include/ent/detail.h create mode 100644 include/ent/ent.h create mode 100644 meson.build create mode 100644 src/ent.c diff --git a/README.md b/README.md new file mode 100644 index 000000000..9d7469c59 --- /dev/null +++ b/README.md @@ -0,0 +1,4 @@ +libent is a simple cross-platform entropy gathering library. It tries +to use the best available source of randomness, and is meant to be used +in applications that need high-quality entropy, e.g. for generating +cryptographic keys. diff --git a/include/ent/detail.h b/include/ent/detail.h new file mode 100644 index 000000000..9eb0e029c --- /dev/null +++ b/include/ent/detail.h @@ -0,0 +1,26 @@ +#ifndef _LIBENT_DETAIL_H +#define _LIBENT_DETAIL_H + +#if defined _WIN32 || defined __CYGWIN__ +# ifdef WIN_EXPORT +# ifdef __GNUC__ +# define ENT_EXPORT __attribute__ ((dllexport)) +# else +# define ENT_EXPORT __declspec(dllexport) +# endif +# else +# ifdef __GNUC__ +# define ENT_EXPORT __attribute__ ((dllimport)) +# else +# define ENT_EXPORT __declspec(dllimport) +# endif +# endif +#else +# if __GNUC__ >= 4 +# define ENT_EXPORT __attribute__ ((visibility ("default"))) +# else +# define ENT_EXPORT +# endif +#endif + +#endif /* _LIBENT_DETAIL_H */ diff --git a/include/ent/ent.h b/include/ent/ent.h new file mode 100644 index 000000000..c06020dca --- /dev/null +++ b/include/ent/ent.h @@ -0,0 +1,12 @@ +#ifndef _LIBENT_ENT_H +#define _LIBENT_ENT_H + +#include + +#include + +ENT_EXPORT +int +ent_getentropy(void *buf, size_t buflen); + +#endif /* _LIBENT_ENT_H */ diff --git a/meson.build b/meson.build new file mode 100644 index 000000000..8b660c4cd --- /dev/null +++ b/meson.build @@ -0,0 +1,21 @@ +project('libent', 'c', 'cpp', + default_options : ['c_std=c99', 'cpp_std=c++11'], + version : '0.0.1', + license : 'MIT') + +inc = include_directories('include') + +install_headers('include/ent/ent.h', subdir : 'ent') + +ent_sources = ['src/ent.c'] +libent = shared_library('ent', + ent_sources, + include_directories : inc, + install : true) + +pkg_mod = import('pkgconfig') +pkg_mod.generate(libraries : libent, + version : '0.0', + name : 'libent', + filebase : 'ent', + description : 'A library to get entropy.') diff --git a/src/ent.c b/src/ent.c new file mode 100644 index 000000000..4f0ec721b --- /dev/null +++ b/src/ent.c @@ -0,0 +1,17 @@ +#include + +#if defined __OPENBSD__ || (defined __linux__ && defined _DEFAULT_SOURCE) +# include +# define getentropy_impl getentropy +#elif defined __APPLE__ && defined __MACH__ +# include +# define getentropy_impl getentropy +#else +# error "Port: getentropy unimplemented" +#endif + +int +ent_getentropy(void *buf, size_t buflen) +{ + return getentropy_impl(buf, buflen); +} From a9f39225c5502b7d8948dc195292db80a5814834 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C5=8Dshin?= Date: Tue, 25 Dec 2018 19:49:36 -0800 Subject: [PATCH 02/43] Fix build on OS X --- src/ent.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ent.c b/src/ent.c index 4f0ec721b..f128ad5e0 100644 --- a/src/ent.c +++ b/src/ent.c @@ -4,6 +4,7 @@ # include # define getentropy_impl getentropy #elif defined __APPLE__ && defined __MACH__ +# include # include # define getentropy_impl getentropy #else From 7a7e7b30f8fe09a04d9eb6c328b73dbdaff0ef07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C5=8Dshin?= Date: Thu, 27 Dec 2018 06:03:44 +0000 Subject: [PATCH 03/43] Simpler implementation --- include/ent.h | 17 +++++++++++++++++ include/ent/detail.h | 26 -------------------------- include/ent/ent.h | 12 ------------ meson.build | 26 ++++++++++++++++++++++++-- src/ent.c | 41 +++++++++++++++++++++++++++++++++++------ 5 files changed, 76 insertions(+), 46 deletions(-) create mode 100644 include/ent.h delete mode 100644 include/ent/detail.h delete mode 100644 include/ent/ent.h diff --git a/include/ent.h b/include/ent.h new file mode 100644 index 000000000..b2a217ca2 --- /dev/null +++ b/include/ent.h @@ -0,0 +1,17 @@ +#ifndef _ENT_H +#define _ENT_H + +#include + +/* + * Fills buf with high-quality entropy. + * + * buflen is the number of bytes, no greater than 256. + * + * Returns 0 on success. On failure, returns -1 and sets errno to + * indicate the error. + */ +int +ent_getentropy(void* buf, size_t buflen); + +#endif /* _ENT_H */ diff --git a/include/ent/detail.h b/include/ent/detail.h deleted file mode 100644 index 9eb0e029c..000000000 --- a/include/ent/detail.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef _LIBENT_DETAIL_H -#define _LIBENT_DETAIL_H - -#if defined _WIN32 || defined __CYGWIN__ -# ifdef WIN_EXPORT -# ifdef __GNUC__ -# define ENT_EXPORT __attribute__ ((dllexport)) -# else -# define ENT_EXPORT __declspec(dllexport) -# endif -# else -# ifdef __GNUC__ -# define ENT_EXPORT __attribute__ ((dllimport)) -# else -# define ENT_EXPORT __declspec(dllimport) -# endif -# endif -#else -# if __GNUC__ >= 4 -# define ENT_EXPORT __attribute__ ((visibility ("default"))) -# else -# define ENT_EXPORT -# endif -#endif - -#endif /* _LIBENT_DETAIL_H */ diff --git a/include/ent/ent.h b/include/ent/ent.h deleted file mode 100644 index c06020dca..000000000 --- a/include/ent/ent.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef _LIBENT_ENT_H -#define _LIBENT_ENT_H - -#include - -#include - -ENT_EXPORT -int -ent_getentropy(void *buf, size_t buflen); - -#endif /* _LIBENT_ENT_H */ diff --git a/meson.build b/meson.build index 8b660c4cd..3e48f1f77 100644 --- a/meson.build +++ b/meson.build @@ -3,11 +3,33 @@ project('libent', 'c', 'cpp', version : '0.0.1', license : 'MIT') -inc = include_directories('include') +conf_data = configuration_data() +compiler = meson.get_compiler('c') -install_headers('include/ent/ent.h', subdir : 'ent') +code = '''#include +#include +int main() { return getentropy((void*)0, 0); } +''' +have_getentropy = compiler.links(code,name : 'system getentropy') +conf_data.set('USE_GETENTROPY', have_getentropy) + +if not have_getentropy + code = '''#include + int main() { return -1 != open("/dev/urandom", O_RDONLY) ? 0 : 1; } + ''' + use_urandom = compiler.run(code, name : 'open /dev/urandom') + conf_data.set('USE_URANDOM', use_urandom.returncode() == 0) +endif + +configure_file(output : 'config.h', + configuration : conf_data) + +inc = include_directories('.', 'include') + +install_headers('include/ent.h') ent_sources = ['src/ent.c'] + libent = shared_library('ent', ent_sources, include_directories : inc, diff --git a/src/ent.c b/src/ent.c index f128ad5e0..ae6c44277 100644 --- a/src/ent.c +++ b/src/ent.c @@ -1,14 +1,43 @@ -#include +#include -#if defined __OPENBSD__ || (defined __linux__ && defined _DEFAULT_SOURCE) +#include + +#include "config.h" + +#if defined(USE_GETENTROPY) # include +# if defined(__APPLE__) || defined(__linux__) +# include +# endif # define getentropy_impl getentropy -#elif defined __APPLE__ && defined __MACH__ +#elif defined(USE_URANDOM) +# include +# include # include -# include -# define getentropy_impl getentropy #else -# error "Port: getentropy unimplemented" +# error "port: getentropy" +#endif + + +#if defined(USE_URANDOM) + +static int +getentropy_impl(void* buf, size_t buflen) +{ + int fd; + + assert(buflen <= 256); + if (-1 == (fd = open("/dev/urandom", O_RDONLY))) { + return -1; + } + if (buflen != read(fd, buf, buflen)) { + (void) close(fd); + return -1; + } + close(fd); + return 0; +} + #endif int From 8ef34bea65ea5d6dc9e5ea67c95a3cb61f13bfe9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C5=8Dshin?= Date: Thu, 27 Dec 2018 10:27:28 -0800 Subject: [PATCH 04/43] blargh fighting with meson --- .gitignore | 1 + src/ent.c => ent.c | 0 include/{ => ent}/ent.h | 2 ++ include/ent/meson.build | 23 +++++++++++++++++++++++ meson.build | 29 ++++------------------------- 5 files changed, 30 insertions(+), 25 deletions(-) create mode 100644 .gitignore rename src/ent.c => ent.c (100%) rename include/{ => ent}/ent.h (92%) create mode 100644 include/ent/meson.build diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..796b96d1c --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/build diff --git a/src/ent.c b/ent.c similarity index 100% rename from src/ent.c rename to ent.c diff --git a/include/ent.h b/include/ent/ent.h similarity index 92% rename from include/ent.h rename to include/ent/ent.h index b2a217ca2..f362a3596 100644 --- a/include/ent.h +++ b/include/ent/ent.h @@ -3,6 +3,8 @@ #include +#include + /* * Fills buf with high-quality entropy. * diff --git a/include/ent/meson.build b/include/ent/meson.build new file mode 100644 index 000000000..134f391af --- /dev/null +++ b/include/ent/meson.build @@ -0,0 +1,23 @@ +conf_data = configuration_data() +compiler = meson.get_compiler('c') + +code = '''#include +#include +int main() { return getentropy((void*)0, 0); } +''' +have_getentropy = compiler.links(code, name : 'system getentropy') +conf_data.set('ENT_USE_GETENTROPY', have_getentropy) + +if not have_getentropy + code = '''#include + int main() { return -1 != open("/dev/urandom", O_RDONLY) ? 0 : 1; } + ''' + use_urandom = compiler.run(code, name : 'open /dev/urandom') + conf_data.set('ENT_USE_URANDOM', use_urandom.returncode() == 0) +endif + +configure_file(output : 'config.h', + configuration : conf_data, + install_dir : 'include/ent') + +install_headers('ent.h', subdir : 'ent') diff --git a/meson.build b/meson.build index 3e48f1f77..4c4024dc6 100644 --- a/meson.build +++ b/meson.build @@ -3,34 +3,13 @@ project('libent', 'c', 'cpp', version : '0.0.1', license : 'MIT') -conf_data = configuration_data() -compiler = meson.get_compiler('c') +subdir('include/ent') -code = '''#include -#include -int main() { return getentropy((void*)0, 0); } -''' -have_getentropy = compiler.links(code,name : 'system getentropy') -conf_data.set('USE_GETENTROPY', have_getentropy) +inc = include_directories('include') -if not have_getentropy - code = '''#include - int main() { return -1 != open("/dev/urandom", O_RDONLY) ? 0 : 1; } - ''' - use_urandom = compiler.run(code, name : 'open /dev/urandom') - conf_data.set('USE_URANDOM', use_urandom.returncode() == 0) -endif +ent_sources = ['ent.c'] -configure_file(output : 'config.h', - configuration : conf_data) - -inc = include_directories('.', 'include') - -install_headers('include/ent.h') - -ent_sources = ['src/ent.c'] - -libent = shared_library('ent', +libent = both_libraries('ent', ent_sources, include_directories : inc, install : true) From f1b44b42a993172e451db558cae64d809d633afa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C5=8Dshin?= Date: Thu, 27 Dec 2018 10:56:10 -0800 Subject: [PATCH 05/43] Get it working --- ent.c | 32 ++++++-------------------------- include/ent/ent.h | 19 +++++++++++++++++-- include/ent/meson.build | 20 +++++++++++++++----- meson.build | 9 ++++++--- 4 files changed, 44 insertions(+), 36 deletions(-) diff --git a/ent.c b/ent.c index ae6c44277..7ac88b286 100644 --- a/ent.c +++ b/ent.c @@ -1,28 +1,14 @@ -#include +#include -#include - -#include "config.h" - -#if defined(USE_GETENTROPY) -# include -# if defined(__APPLE__) || defined(__linux__) -# include -# endif -# define getentropy_impl getentropy -#elif defined(USE_URANDOM) +#if defined(ENT_USE_URANDOM) +# include # include # include # include -#else -# error "port: getentropy" -#endif -#if defined(USE_URANDOM) - -static int -getentropy_impl(void* buf, size_t buflen) +int +ent_getentropy(void* buf, size_t buflen) { int fd; @@ -38,10 +24,4 @@ getentropy_impl(void* buf, size_t buflen) return 0; } -#endif - -int -ent_getentropy(void *buf, size_t buflen) -{ - return getentropy_impl(buf, buflen); -} +#endif /* ENT_USE_URANDOM */ diff --git a/include/ent/ent.h b/include/ent/ent.h index f362a3596..cecf3ce1d 100644 --- a/include/ent/ent.h +++ b/include/ent/ent.h @@ -1,10 +1,21 @@ #ifndef _ENT_H #define _ENT_H -#include - #include +#if defined(ENT_GETENTROPY) +# if defined(ENT_GE_SYSRANDOM) +# include +# include /* OSX sys/random.h needs Availability.h from this */ +# include +# elif defined(ENT_GE_UNISTD) +# include +# else +# error "libent: this shouldn't happen" +# endif +# define ent_getentropy getentropy +#elif defined(ENT_URANDOM) + /* * Fills buf with high-quality entropy. * @@ -16,4 +27,8 @@ int ent_getentropy(void* buf, size_t buflen); +#else +# error "libent: platform not supported" +#endif + #endif /* _ENT_H */ diff --git a/include/ent/meson.build b/include/ent/meson.build index 134f391af..2f6df5a55 100644 --- a/include/ent/meson.build +++ b/include/ent/meson.build @@ -1,19 +1,29 @@ conf_data = configuration_data() compiler = meson.get_compiler('c') -code = '''#include +code = '''#include +#include /* OSX sys/random.h needs Availability.h from this */ #include int main() { return getentropy((void*)0, 0); } ''' -have_getentropy = compiler.links(code, name : 'system getentropy') -conf_data.set('ENT_USE_GETENTROPY', have_getentropy) +sysrandom = compiler.links(code, name : 'getentropy in sys/random.h') +conf_data.set('ENT_GE_SYSRANDOM', sysrandom) + +code = '''#include +int main() { return getentropy((void*)0, 0); } +''' +unistd = compiler.links(code, name : 'getentropy is in unistd.h') +conf_data.set('ENT_GE_UNISTD', unistd) + +have_getentropy = sysrandom or unistd +conf_data.set('ENT_GETENTROPY', have_getentropy) if not have_getentropy code = '''#include int main() { return -1 != open("/dev/urandom", O_RDONLY) ? 0 : 1; } ''' - use_urandom = compiler.run(code, name : 'open /dev/urandom') - conf_data.set('ENT_USE_URANDOM', use_urandom.returncode() == 0) + use_urandom = compiler.run(code, name : 'can open /dev/urandom') + conf_data.set('ENT_URANDOM', use_urandom.returncode() == 0) endif configure_file(output : 'config.h', diff --git a/meson.build b/meson.build index 4c4024dc6..ed2ff2b78 100644 --- a/meson.build +++ b/meson.build @@ -9,10 +9,13 @@ inc = include_directories('include') ent_sources = ['ent.c'] +ent_dep = declare_dependency(sources : ent_sources, + compile_args : ['-Wall', '-pedantic'], + include_directories : inc) + libent = both_libraries('ent', - ent_sources, - include_directories : inc, - install : true) + dependencies : [ent_dep], + install : false) pkg_mod = import('pkgconfig') pkg_mod.generate(libraries : libent, From 30390fa180f9f3502086ed851393482b64421e8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C5=8Dshin?= Date: Thu, 27 Dec 2018 11:06:22 -0800 Subject: [PATCH 06/43] More robust read loop --- ent.c | 35 +++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/ent.c b/ent.c index 7ac88b286..522960bca 100644 --- a/ent.c +++ b/ent.c @@ -1,27 +1,38 @@ #include -#if defined(ENT_USE_URANDOM) -# include -# include -# include -# include +#if defined(ENT_URANDOM) + +#include +#include +#include +#include int -ent_getentropy(void* buf, size_t buflen) +ent_getentropy(void* buf, size_t len) { int fd; + ssize_t ret; - assert(buflen <= 256); + assert(len <= 256); if (-1 == (fd = open("/dev/urandom", O_RDONLY))) { return -1; } - if (buflen != read(fd, buf, buflen)) { - (void) close(fd); - return -1; + while (len != 0 && (ret = read(fd, buf, len)) != 0) { + if (ret == -1) { + if (errno == EINTR) + continue; + break; + } + len -= ret; + buf += ret; } - close(fd); - return 0; + (void) close(fd); + if (ret == 0) { + ret = -1; + errno = EIO; + } + return ret < 0 ? ret : 0; } #endif /* ENT_USE_URANDOM */ From 16451c769c57ed942f9bda241bb16b25a4f9320e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C5=8Dshin?= Date: Thu, 27 Dec 2018 19:13:51 +0000 Subject: [PATCH 07/43] Fix on Linux --- ent.c | 10 ++++++---- include/ent/ent.h | 3 ++- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/ent.c b/ent.c index 522960bca..31b81f132 100644 --- a/ent.c +++ b/ent.c @@ -3,29 +3,31 @@ #if defined(ENT_URANDOM) #include +#include +#include #include #include -#include int ent_getentropy(void* buf, size_t len) { - int fd; + int fd; ssize_t ret; + char* cuf; assert(len <= 256); if (-1 == (fd = open("/dev/urandom", O_RDONLY))) { return -1; } - while (len != 0 && (ret = read(fd, buf, len)) != 0) { + while (len != 0 && (ret = read(fd, cuf, len)) != 0) { if (ret == -1) { if (errno == EINTR) continue; break; } len -= ret; - buf += ret; + cuf += ret; } (void) close(fd); if (ret == 0) { diff --git a/include/ent/ent.h b/include/ent/ent.h index cecf3ce1d..db6caf7f0 100644 --- a/include/ent/ent.h +++ b/include/ent/ent.h @@ -3,9 +3,10 @@ #include +#include + #if defined(ENT_GETENTROPY) # if defined(ENT_GE_SYSRANDOM) -# include # include /* OSX sys/random.h needs Availability.h from this */ # include # elif defined(ENT_GE_UNISTD) From 4d89cad020f7c1fc87f49e82d6ee4958529ce11e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C5=8Dshin?= Date: Thu, 27 Dec 2018 19:19:59 +0000 Subject: [PATCH 08/43] Add a sample program --- ent.c | 2 +- meson.build | 4 ++++ sample.c | 22 ++++++++++++++++++++++ 3 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 sample.c diff --git a/ent.c b/ent.c index 31b81f132..9ac48d82d 100644 --- a/ent.c +++ b/ent.c @@ -14,7 +14,7 @@ ent_getentropy(void* buf, size_t len) { int fd; ssize_t ret; - char* cuf; + char* cuf = buf; assert(len <= 256); if (-1 == (fd = open("/dev/urandom", O_RDONLY))) { diff --git a/meson.build b/meson.build index ed2ff2b78..d2fd3a068 100644 --- a/meson.build +++ b/meson.build @@ -23,3 +23,7 @@ pkg_mod.generate(libraries : libent, name : 'libent', filebase : 'ent', description : 'A library to get entropy.') + +ent_sample = executable('sample', + ['sample.c'], + dependencies : [ent_dep]) diff --git a/sample.c b/sample.c new file mode 100644 index 000000000..f057313ab --- /dev/null +++ b/sample.c @@ -0,0 +1,22 @@ +#include +#include + +#include + + +int +main() +{ + char buf[256]; + int i; + + memset(buf, 0, sizeof(buf)); + if (0 != ent_getentropy(buf, sizeof(buf))) { + perror("getentropy"); + } + for (i = 0; i < sizeof buf; ++i) { + printf("%02hhx", buf[i]); + } + puts(""); + return 0; +} From 38cf11ed344f0cfa4043cfab1b173b51b817da5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C5=8Dshin?= Date: Thu, 27 Dec 2018 11:43:48 -0800 Subject: [PATCH 09/43] Cleanup, MIT license --- LICENSE | 20 ++++++++++++++++++++ README.md | 12 ++++++++---- include/ent/ent.h | 16 ++++++++++++++-- 3 files changed, 42 insertions(+), 6 deletions(-) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 000000000..2aef9ab4d --- /dev/null +++ b/LICENSE @@ -0,0 +1,20 @@ +Copyright 2018 Steven Dee + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md index 9d7469c59..7bfa490dd 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,8 @@ -libent is a simple cross-platform entropy gathering library. It tries -to use the best available source of randomness, and is meant to be used -in applications that need high-quality entropy, e.g. for generating -cryptographic keys. +libent is a cross-platform wrapper around `getentropy(2)`. It exports +one symbol, `ent_getentropy`, which expands to `getentropy` if the +latter is available. Otherwise, it tries to use the next best source of +entropy -- /dev/urandom on *nix, BCryptGenRandom on Windows. + +References: +* [OpenBSD getentropy](https://man.openbsd.org/cgi-bin/man.cgi/OpenBSD-current/man2/getentropy.2) +* [djb on entropy gathering](https://blog.cr.yp.to/20140205-entropy.html) diff --git a/include/ent/ent.h b/include/ent/ent.h index db6caf7f0..78b646437 100644 --- a/include/ent/ent.h +++ b/include/ent/ent.h @@ -1,10 +1,10 @@ #ifndef _ENT_H #define _ENT_H -#include - #include +#include + #if defined(ENT_GETENTROPY) # if defined(ENT_GE_SYSRANDOM) # include /* OSX sys/random.h needs Availability.h from this */ @@ -32,4 +32,16 @@ ent_getentropy(void* buf, size_t buflen); # error "libent: platform not supported" #endif +#ifdef ENT_GETENTROPY +#undef ENT_GETENTROPY +#endif + +#ifdef ENT_GE_SYSRANDOM +#undef ENT_GE_SYSRANDOM +#endif + +#ifdef ENT_GE_UNISTD +#undef ENT_GE_UNISTD +#endif + #endif /* _ENT_H */ From 59102acc59d317c5435f8c5c0eafc4fec7e3fa80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C5=8Dshin?= Date: Thu, 27 Dec 2018 11:53:34 -0800 Subject: [PATCH 10/43] Rename dep --- meson.build | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/meson.build b/meson.build index d2fd3a068..82b6b5fa5 100644 --- a/meson.build +++ b/meson.build @@ -9,12 +9,12 @@ inc = include_directories('include') ent_sources = ['ent.c'] -ent_dep = declare_dependency(sources : ent_sources, - compile_args : ['-Wall', '-pedantic'], - include_directories : inc) +libent_dep = declare_dependency(sources : ent_sources, + compile_args : ['-Wall', '-pedantic'], + include_directories : inc) libent = both_libraries('ent', - dependencies : [ent_dep], + dependencies : [libent_dep], install : false) pkg_mod = import('pkgconfig') @@ -26,4 +26,4 @@ pkg_mod.generate(libraries : libent, ent_sample = executable('sample', ['sample.c'], - dependencies : [ent_dep]) + dependencies : [libent_dep]) From ff8fa84e28d73e15c91eb72a03cc4c90c08aefb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C5=8Dshin?= Date: Thu, 27 Dec 2018 11:55:40 -0800 Subject: [PATCH 11/43] Remove pedantic arg --- meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meson.build b/meson.build index 82b6b5fa5..9fe189122 100644 --- a/meson.build +++ b/meson.build @@ -10,7 +10,7 @@ inc = include_directories('include') ent_sources = ['ent.c'] libent_dep = declare_dependency(sources : ent_sources, - compile_args : ['-Wall', '-pedantic'], + compile_args : ['-Wall'], include_directories : inc) libent = both_libraries('ent', From 97b072ef6d4537f45549dc240d6ce7d2ea6fe7c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C5=8Dshin?= Date: Thu, 27 Dec 2018 12:05:15 -0800 Subject: [PATCH 12/43] warn about urandom --- ent.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ent.c b/ent.c index 9ac48d82d..1369ec431 100644 --- a/ent.c +++ b/ent.c @@ -2,6 +2,8 @@ #if defined(ENT_URANDOM) +#warning "libent: using /dev/urandom..." + #include #include #include From 4cbc082504396f0bdb05d68e040fca5b2cd8ba0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C5=8Dshin?= Date: Thu, 27 Dec 2018 12:17:10 -0800 Subject: [PATCH 13/43] Expand README --- README.md | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 7bfa490dd..43aba314f 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,23 @@ libent is a cross-platform wrapper around `getentropy(2)`. It exports one symbol, `ent_getentropy`, which expands to `getentropy` if the latter is available. Otherwise, it tries to use the next best source of -entropy -- /dev/urandom on *nix, BCryptGenRandom on Windows. +entropy — `/dev/urandom` on *nix. + +### Why? + +`getentropy` is the wave of the future. It's the correct API for +generating small amounts of entropy to create cryptographic keys or seed +PRNGs. It's good and reasonable and true, it's on Linux, *BSD, and OS X, +and it only took us fifty years of UNIX to get here. + +Sadly, it only just arrived, so nobody has it yet. It didn't land in +Linux until glibc 2.25, which seems to only have made it into Debian 10. + +Once `getentropy` is everywhere you care about, you can just do a +s/ent_//g on all the call sites and discard this shim. + +Admittedly, 90% of the motivation behind this was to fix the randomness +shim in [Urbit](https://github.com/urbit/urbit). References: * [OpenBSD getentropy](https://man.openbsd.org/cgi-bin/man.cgi/OpenBSD-current/man2/getentropy.2) From 6d2e6b168fd537939294f1b7dd8270a4a8afe97a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C5=8Dshin?= Date: Thu, 27 Dec 2018 12:27:02 -0800 Subject: [PATCH 14/43] Rejigger the meson file --- meson.build | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/meson.build b/meson.build index 9fe189122..b057a5e0b 100644 --- a/meson.build +++ b/meson.build @@ -1,4 +1,4 @@ -project('libent', 'c', 'cpp', +project('libent', 'c', default_options : ['c_std=c99', 'cpp_std=c++11'], version : '0.0.1', license : 'MIT') @@ -9,14 +9,14 @@ inc = include_directories('include') ent_sources = ['ent.c'] -libent_dep = declare_dependency(sources : ent_sources, - compile_args : ['-Wall'], - include_directories : inc) - -libent = both_libraries('ent', - dependencies : [libent_dep], +libent = static_library('ent', + sources : ent_sources, + include_directories : inc, + c_args : ['-Wall', '-pedantic'], install : false) +libent_dep = declare_dependency(include_directories : inc, link_with : libent) + pkg_mod = import('pkgconfig') pkg_mod.generate(libraries : libent, version : '0.0', From ae716220e225fc2934c60da6343ecaded1904a37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C5=8Dshin?= Date: Thu, 27 Dec 2018 12:31:36 -0800 Subject: [PATCH 15/43] Remove pkg_mod stuff --- meson.build | 7 ------- 1 file changed, 7 deletions(-) diff --git a/meson.build b/meson.build index b057a5e0b..bba9682e8 100644 --- a/meson.build +++ b/meson.build @@ -17,13 +17,6 @@ libent = static_library('ent', libent_dep = declare_dependency(include_directories : inc, link_with : libent) -pkg_mod = import('pkgconfig') -pkg_mod.generate(libraries : libent, - version : '0.0', - name : 'libent', - filebase : 'ent', - description : 'A library to get entropy.') - ent_sample = executable('sample', ['sample.c'], dependencies : [libent_dep]) From 3152f00a8d7853aa038cb48a767ffe3d246ce4bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C5=8Dshin?= Date: Thu, 27 Dec 2018 16:32:15 -0800 Subject: [PATCH 16/43] License header in public include --- include/ent/ent.h | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/include/ent/ent.h b/include/ent/ent.h index 78b646437..d92aaed47 100644 --- a/include/ent/ent.h +++ b/include/ent/ent.h @@ -1,3 +1,24 @@ +/* Copyright 2018 Steven Dee. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ #ifndef _ENT_H #define _ENT_H @@ -17,8 +38,7 @@ # define ent_getentropy getentropy #elif defined(ENT_URANDOM) -/* - * Fills buf with high-quality entropy. +/* Fills buf with high-quality entropy. * * buflen is the number of bytes, no greater than 256. * From f8b9b2fc38ccfaaa828439162cf37fe03f9aae6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C5=8Dshin?= Date: Thu, 27 Dec 2018 16:32:30 -0800 Subject: [PATCH 17/43] Prefer sysrandom in meson.build --- include/ent/meson.build | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/include/ent/meson.build b/include/ent/meson.build index 2f6df5a55..314213e15 100644 --- a/include/ent/meson.build +++ b/include/ent/meson.build @@ -8,14 +8,17 @@ int main() { return getentropy((void*)0, 0); } ''' sysrandom = compiler.links(code, name : 'getentropy in sys/random.h') conf_data.set('ENT_GE_SYSRANDOM', sysrandom) +have_getentropy = sysrandom -code = '''#include -int main() { return getentropy((void*)0, 0); } -''' -unistd = compiler.links(code, name : 'getentropy is in unistd.h') -conf_data.set('ENT_GE_UNISTD', unistd) +if not have_getentropy + code = '''#include + int main() { return getentropy((void*)0, 0); } + ''' + unistd = compiler.links(code, name : 'getentropy is in unistd.h') + conf_data.set('ENT_GE_UNISTD', unistd) + have_getentropy = unistd +endif -have_getentropy = sysrandom or unistd conf_data.set('ENT_GETENTROPY', have_getentropy) if not have_getentropy From 758adeccaaead446f82f25d7944d240a7a7ec05e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C5=8Dshin?= Date: Thu, 27 Dec 2018 16:42:28 -0800 Subject: [PATCH 18/43] pragma once --- include/ent/ent.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/include/ent/ent.h b/include/ent/ent.h index d92aaed47..eee99d2fb 100644 --- a/include/ent/ent.h +++ b/include/ent/ent.h @@ -19,8 +19,8 @@ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#ifndef _ENT_H -#define _ENT_H + +#pragma once #include @@ -63,5 +63,3 @@ ent_getentropy(void* buf, size_t buflen); #ifdef ENT_GE_UNISTD #undef ENT_GE_UNISTD #endif - -#endif /* _ENT_H */ From 67f6fa28aa5aa35ef23db068b9ddb391bdfc8189 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C5=8Dshin?= Date: Thu, 27 Dec 2018 16:50:27 -0800 Subject: [PATCH 19/43] Don't install headers --- include/ent/meson.build | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/include/ent/meson.build b/include/ent/meson.build index 314213e15..547dbc6d3 100644 --- a/include/ent/meson.build +++ b/include/ent/meson.build @@ -30,7 +30,4 @@ if not have_getentropy endif configure_file(output : 'config.h', - configuration : conf_data, - install_dir : 'include/ent') - -install_headers('ent.h', subdir : 'ent') + configuration : conf_data) From 9605372b940372582b93cabbdcad77569bd282a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C5=8Dshin?= Date: Thu, 27 Dec 2018 18:38:54 -0800 Subject: [PATCH 20/43] Succeed on 0-length calls --- ent.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ent.c b/ent.c index 1369ec431..2eff4c615 100644 --- a/ent.c +++ b/ent.c @@ -19,6 +19,8 @@ ent_getentropy(void* buf, size_t len) char* cuf = buf; assert(len <= 256); + if (!len) + return 0; if (-1 == (fd = open("/dev/urandom", O_RDONLY))) { return -1; } From 6e42521ee8c2fa92c10ab968073c28e140878521 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C5=8Dshin?= Date: Thu, 27 Dec 2018 18:43:23 -0800 Subject: [PATCH 21/43] Exit on failure in sample --- sample.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sample.c b/sample.c index f057313ab..881a0df2a 100644 --- a/sample.c +++ b/sample.c @@ -1,4 +1,5 @@ #include +#include #include #include @@ -13,6 +14,7 @@ main() memset(buf, 0, sizeof(buf)); if (0 != ent_getentropy(buf, sizeof(buf))) { perror("getentropy"); + exit(1); } for (i = 0; i < sizeof buf; ++i) { printf("%02hhx", buf[i]); From b557d1c50cce283554d14f264ff3e265fd6da732 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C5=8Dshin?= Date: Mon, 31 Dec 2018 17:19:28 +0000 Subject: [PATCH 22/43] Use getrandom --- README.md | 36 ++++++++++++++++++++------- ent.c | 55 ++++++++++++++++++++++++++++++----------- include/ent/ent.h | 10 +++++++- include/ent/meson.build | 55 ++++++++++++++++++++++++++--------------- meson_options.txt | 2 ++ 5 files changed, 114 insertions(+), 44 deletions(-) create mode 100644 meson_options.txt diff --git a/README.md b/README.md index 43aba314f..72267a151 100644 --- a/README.md +++ b/README.md @@ -1,24 +1,42 @@ libent is a cross-platform wrapper around `getentropy(2)`. It exports -one symbol, `ent_getentropy`, which expands to `getentropy` if the -latter is available. Otherwise, it tries to use the next best source of -entropy — `/dev/urandom` on *nix. +one symbol, `ent_getentropy`. If `getentropy` is available, then it's +just a macro that expands to that. Otherwise, it uses `getrandom(2)` +(available since kernel 3.17) on Linux, or `/dev/urandom` on other +\*nix. + +### Building + +It uses meson. `meson ./build && ninja -C build` should do the trick. + +#### Build options + +It has one option, `support-older-oses`, which tells it to be +conservative. On Linux, this means using `getrandom` directly; on other +\*nix, it means opening `/dev/urandom`. This may make sense if you want +your binaries to run on older versions of the same OS. If your program +is mostly built from source, don't bother. ### Why? `getentropy` is the wave of the future. It's the correct API for generating small amounts of entropy to create cryptographic keys or seed -PRNGs. It's good and reasonable and true, it's on Linux, *BSD, and OS X, -and it only took us fifty years of UNIX to get here. +PRNGs. It's good and reasonable and true, it's on Linux, \*BSD, and OS +X, and it only took us fifty years of UNIX to get here. Sadly, it only just arrived, so nobody has it yet. It didn't land in Linux until glibc 2.25, which seems to only have made it into Debian 10. Once `getentropy` is everywhere you care about, you can just do a -s/ent_//g on all the call sites and discard this shim. +s/ent\_//g on all the call sites and discard this shim. -Admittedly, 90% of the motivation behind this was to fix the randomness -shim in [Urbit](https://github.com/urbit/urbit). +This project began because [Urbit](https://github.com/urbit/urbit)'s +entropy-generation function was bothering me. Then it got out of hand. + +### What about Windows? + +I'm happy to receive donations or pull requests. + +### References -References: * [OpenBSD getentropy](https://man.openbsd.org/cgi-bin/man.cgi/OpenBSD-current/man2/getentropy.2) * [djb on entropy gathering](https://blog.cr.yp.to/20140205-entropy.html) diff --git a/ent.c b/ent.c index 2eff4c615..43e5a3f43 100644 --- a/ent.c +++ b/ent.c @@ -1,31 +1,58 @@ -#include +#include + +/* ent.h undefs these constants and config.h is #pragma once. */ + +#if defined(ENT_GETRANDOM) +#define _ENT_GETRANDOM +#define _GNU_SOURCE +#endif #if defined(ENT_URANDOM) +#define _ENT_URANDOM +#endif -#warning "libent: using /dev/urandom..." +#include #include #include #include -#include -#include +#if defined(_ENT_GETRANDOM) + +#include + +#elif defined(_ENT_URANDOM) + +#include +#include +#include + +#endif int ent_getentropy(void* buf, size_t len) { - int fd; - ssize_t ret; - char* cuf = buf; + char *cuf = buf; + int ret; +#if defined(_ENT_URANDOM) + int fd; +#endif assert(len <= 256); if (!len) return 0; - if (-1 == (fd = open("/dev/urandom", O_RDONLY))) { +#if defined(_ENT_URANDOM) + if ((fd = open("/dev/urandom", O_RDONLY)) < 0) return -1; - } - while (len != 0 && (ret = read(fd, cuf, len)) != 0) { - if (ret == -1) { +#endif + while (len && +#if defined(_ENT_GETRANDOM) + (ret = syscall(SYS_getrandom, cuf, len, 0)) != 0 +#elif defined(_ENT_URANDOM) + (ret = read(fd, cuf, len)) != 0 +#endif + ) { + if (ret < 0) { if (errno == EINTR) continue; break; @@ -33,12 +60,12 @@ ent_getentropy(void* buf, size_t len) len -= ret; cuf += ret; } +#if defined(_ENT_URANDOM) (void) close(fd); - if (ret == 0) { +#endif + if (!ret) { ret = -1; errno = EIO; } return ret < 0 ? ret : 0; } - -#endif /* ENT_USE_URANDOM */ diff --git a/include/ent/ent.h b/include/ent/ent.h index eee99d2fb..6b3a23845 100644 --- a/include/ent/ent.h +++ b/include/ent/ent.h @@ -36,7 +36,7 @@ # error "libent: this shouldn't happen" # endif # define ent_getentropy getentropy -#elif defined(ENT_URANDOM) +#elif defined(ENT_GETRANDOM) || defined(ENT_URANDOM) /* Fills buf with high-quality entropy. * @@ -63,3 +63,11 @@ ent_getentropy(void* buf, size_t buflen); #ifdef ENT_GE_UNISTD #undef ENT_GE_UNISTD #endif + +#ifdef ENT_GETRANDOM +#undef ENT_GETRANDOM +#endif + +#ifdef ENT_URANDOM +#undef ENT_URANDOM +#endif diff --git a/include/ent/meson.build b/include/ent/meson.build index 547dbc6d3..f7851f01a 100644 --- a/include/ent/meson.build +++ b/include/ent/meson.build @@ -1,33 +1,48 @@ conf_data = configuration_data() compiler = meson.get_compiler('c') +older_oses = get_option('support-older-oses') -code = '''#include -#include /* OSX sys/random.h needs Availability.h from this */ -#include -int main() { return getentropy((void*)0, 0); } -''' -sysrandom = compiler.links(code, name : 'getentropy in sys/random.h') -conf_data.set('ENT_GE_SYSRANDOM', sysrandom) -have_getentropy = sysrandom - -if not have_getentropy - code = '''#include +if not older_oses + code = '''#include + #include /* OSX sys/random.h needs Availability.h from this */ + #include int main() { return getentropy((void*)0, 0); } ''' - unistd = compiler.links(code, name : 'getentropy is in unistd.h') - conf_data.set('ENT_GE_UNISTD', unistd) - have_getentropy = unistd -endif + sysrandom = compiler.links(code, name : 'getentropy in sys/random.h') + conf_data.set('ENT_GE_SYSRANDOM', sysrandom) -conf_data.set('ENT_GETENTROPY', have_getentropy) + if not sysrandom + code = '''#include + int main() { return getentropy((void*)0, 0); } + ''' + unistd = compiler.links(code, name : 'getentropy is in unistd.h') + conf_data.set('ENT_GE_UNISTD', unistd) + endif + have_getentropy = sysrandom or unistd + conf_data.set('ENT_GETENTROPY', have_getentropy) +else + have_getentropy = false +endif if not have_getentropy - code = '''#include - int main() { return -1 != open("/dev/urandom", O_RDONLY) ? 0 : 1; } + code = '''#define _GNU_SOURCE + #include + #include + #include + int main() { return !syscall(__NR_getrandom, (void*)0, 0, 0); } ''' - use_urandom = compiler.run(code, name : 'can open /dev/urandom') - conf_data.set('ENT_URANDOM', use_urandom.returncode() == 0) + getrandom = compiler.links(code, name : 'getrandom syscall available') + conf_data.set('ENT_GETRANDOM', getrandom) + + if not getrandom + code = '''#include + int main() { return open("/dev/urandom", O_RDONLY) >= 0 ? 0 : 1; } + ''' + urandom = compiler.run(code, name : 'can open /dev/urandom').returncode() == 0 + conf_data.set('ENT_URANDOM', urandom) + endif endif + configure_file(output : 'config.h', configuration : conf_data) diff --git a/meson_options.txt b/meson_options.txt new file mode 100644 index 000000000..54379955b --- /dev/null +++ b/meson_options.txt @@ -0,0 +1,2 @@ +option('support-older-oses', type : 'boolean', value : false, + description : 'Tries to work on older systems. Useful for binary releases. (Uses getrandom on Linux, /dev/urandom on other *nix.)') From 12ac12a7956a08eb6fc5120d4718b61e2da318aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C5=8Dshin?= Date: Mon, 31 Dec 2018 09:21:50 -0800 Subject: [PATCH 23/43] Fix build with getentropy --- ent.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ent.c b/ent.c index 43e5a3f43..fee4cd674 100644 --- a/ent.c +++ b/ent.c @@ -13,6 +13,8 @@ #include +#if defined(_ENT_GETRANDOM) || defined(_ENT_URANDOM) + #include #include #include @@ -69,3 +71,5 @@ ent_getentropy(void* buf, size_t len) } return ret < 0 ? ret : 0; } + +#endif /* _ENT_GETRANDOM || _ENT_URANDOM */ From d79967ef393d6896837fdf65bd76b05d221e0c7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C5=8Dshin?= Date: Mon, 31 Dec 2018 09:40:38 -0800 Subject: [PATCH 24/43] Cleanup --- ent.c | 69 ++++++++++++++++++++++++++++------------------------------- 1 file changed, 33 insertions(+), 36 deletions(-) diff --git a/ent.c b/ent.c index fee4cd674..70e595a19 100644 --- a/ent.c +++ b/ent.c @@ -1,59 +1,58 @@ #include -/* ent.h undefs these constants and config.h is #pragma once. */ +/* ent.h undefs all constants and config.h is #pragma once. */ #if defined(ENT_GETRANDOM) -#define _ENT_GETRANDOM + +#define _ENT_IMPL #define _GNU_SOURCE -#endif - -#if defined(ENT_URANDOM) -#define _ENT_URANDOM -#endif - -#include - -#if defined(_ENT_GETRANDOM) || defined(_ENT_URANDOM) - -#include -#include #include - -#if defined(_ENT_GETRANDOM) - #include -#elif defined(_ENT_URANDOM) +#define ENT_DEFS (void)0 +#define ENT_INIT() (void)0 +#define ENT_READ(B, L) sysall(SYS_getrandom, B, L, 0) +#define ENT_FINI() (void)0 +#elif defined(ENT_URANDOM) + +#define _ENT_IMPL +#include #include #include #include +#define ENT_DEFS int fd +#define ENT_INIT() do { \ + if ((fd = open("/dev/urandom", O_RDONLY)) < 0) \ + return -1; \ +} while (0) +#define ENT_READ(B, L) read(fd, B, L) +#define ENT_FINI() (void) close(fd) + #endif + +#include + +#if defined(_ENT_IMPL) + +#include +#include + + int ent_getentropy(void* buf, size_t len) { char *cuf = buf; int ret; -#if defined(_ENT_URANDOM) - int fd; -#endif + ENT_DEFS; assert(len <= 256); if (!len) return 0; -#if defined(_ENT_URANDOM) - if ((fd = open("/dev/urandom", O_RDONLY)) < 0) - return -1; -#endif - while (len && -#if defined(_ENT_GETRANDOM) - (ret = syscall(SYS_getrandom, cuf, len, 0)) != 0 -#elif defined(_ENT_URANDOM) - (ret = read(fd, cuf, len)) != 0 -#endif - ) { + ENT_INIT(); + while (len && (ret = ENT_READ(cuf, len)) != 0) { if (ret < 0) { if (errno == EINTR) continue; @@ -62,9 +61,7 @@ ent_getentropy(void* buf, size_t len) len -= ret; cuf += ret; } -#if defined(_ENT_URANDOM) - (void) close(fd); -#endif + ENT_FINI(); if (!ret) { ret = -1; errno = EIO; @@ -72,4 +69,4 @@ ent_getentropy(void* buf, size_t len) return ret < 0 ? ret : 0; } -#endif /* _ENT_GETRANDOM || _ENT_URANDOM */ +#endif /* _ENT_IMPL */ From 38e15a688e9c0fd83547d7eecf8469a1a8ae1c88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C5=8Dshin?= Date: Mon, 31 Dec 2018 18:02:21 +0000 Subject: [PATCH 25/43] Fix typo --- ent.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ent.c b/ent.c index 70e595a19..20fdb776a 100644 --- a/ent.c +++ b/ent.c @@ -11,7 +11,7 @@ #define ENT_DEFS (void)0 #define ENT_INIT() (void)0 -#define ENT_READ(B, L) sysall(SYS_getrandom, B, L, 0) +#define ENT_READ(B, L) syscall(SYS_getrandom, B, L, 0) #define ENT_FINI() (void)0 #elif defined(ENT_URANDOM) From 441da97aef12b2b7e0fdb8682b0c0f509ff7ee25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C5=8Dshin?= Date: Mon, 31 Dec 2018 11:08:53 -0800 Subject: [PATCH 26/43] Remove ifdefs --- include/ent/ent.h | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/include/ent/ent.h b/include/ent/ent.h index 6b3a23845..03d4ee6e5 100644 --- a/include/ent/ent.h +++ b/include/ent/ent.h @@ -52,22 +52,8 @@ ent_getentropy(void* buf, size_t buflen); # error "libent: platform not supported" #endif -#ifdef ENT_GETENTROPY #undef ENT_GETENTROPY -#endif - -#ifdef ENT_GE_SYSRANDOM #undef ENT_GE_SYSRANDOM -#endif - -#ifdef ENT_GE_UNISTD #undef ENT_GE_UNISTD -#endif - -#ifdef ENT_GETRANDOM #undef ENT_GETRANDOM -#endif - -#ifdef ENT_URANDOM #undef ENT_URANDOM -#endif From 9a1c8d30fb87168ad87552f6f0d752cdbfd87f5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C5=8Dshin?= Date: Mon, 31 Dec 2018 11:11:07 -0800 Subject: [PATCH 27/43] Remove _ --- ent.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ent.c b/ent.c index 20fdb776a..425625187 100644 --- a/ent.c +++ b/ent.c @@ -4,7 +4,7 @@ #if defined(ENT_GETRANDOM) -#define _ENT_IMPL +#define ENT_IMPL #define _GNU_SOURCE #include #include @@ -16,7 +16,7 @@ #elif defined(ENT_URANDOM) -#define _ENT_IMPL +#define ENT_IMPL #include #include #include @@ -35,7 +35,7 @@ #include -#if defined(_ENT_IMPL) +#if defined(ENT_IMPL) #include #include @@ -69,4 +69,4 @@ ent_getentropy(void* buf, size_t len) return ret < 0 ? ret : 0; } -#endif /* _ENT_IMPL */ +#endif /* ENT_IMPL */ From 2471e6a4911fbd331490841d8f028d4f5f6dddad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C5=8Dshin?= Date: Mon, 31 Dec 2018 11:38:03 -0800 Subject: [PATCH 28/43] s/__NR/SYS/ --- include/ent/meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/ent/meson.build b/include/ent/meson.build index f7851f01a..e4bd4e17a 100644 --- a/include/ent/meson.build +++ b/include/ent/meson.build @@ -29,7 +29,7 @@ if not have_getentropy #include #include #include - int main() { return !syscall(__NR_getrandom, (void*)0, 0, 0); } + int main() { return !syscall(SYS_getrandom, (void*)0, 0, 0); } ''' getrandom = compiler.links(code, name : 'getrandom syscall available') conf_data.set('ENT_GETRANDOM', getrandom) From ce933a6c5cf4c4f2623c7024fd2f7abbd3645bb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C5=8Dshin?= Date: Wed, 2 Jan 2019 10:06:47 -0800 Subject: [PATCH 29/43] Simplify - The header is now less brittle, and is the same thing everywhere. - Lots of stuff is cleaned up and simpler. - Changed copyright year. --- LICENSE | 2 +- README.md | 15 +++---- ent.c | 72 ------------------------------- include/ent.h | 34 +++++++++++++++ include/ent/ent.h | 59 -------------------------- include/meson.build | 1 + meson.build | 20 ++------- meson_options.txt | 2 +- sample.c | 2 +- src/ent.c | 73 ++++++++++++++++++++++++++++++++ {include/ent => src}/meson.build | 30 ++++++++----- 11 files changed, 140 insertions(+), 170 deletions(-) delete mode 100644 ent.c create mode 100644 include/ent.h delete mode 100644 include/ent/ent.h create mode 100644 include/meson.build create mode 100644 src/ent.c rename {include/ent => src}/meson.build (50%) diff --git a/LICENSE b/LICENSE index 2aef9ab4d..6cbc4284e 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright 2018 Steven Dee +Copyright 2019 Steven Dee Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/README.md b/README.md index 72267a151..511037f31 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,7 @@ libent is a cross-platform wrapper around `getentropy(2)`. It exports one symbol, `ent_getentropy`. If `getentropy` is available, then it's -just a macro that expands to that. Otherwise, it uses `getrandom(2)` -(available since kernel 3.17) on Linux, or `/dev/urandom` on other -\*nix. +just a shim around that. Otherwise, it uses `getrandom(2)` (available +since kernel 3.17) on Linux, or `/dev/urandom` on other \*nix. ### Building @@ -12,9 +11,9 @@ It uses meson. `meson ./build && ninja -C build` should do the trick. It has one option, `support-older-oses`, which tells it to be conservative. On Linux, this means using `getrandom` directly; on other -\*nix, it means opening `/dev/urandom`. This may make sense if you want -your binaries to run on older versions of the same OS. If your program -is mostly built from source, don't bother. +\*nix, it means reading from `/dev/urandom`. This may make sense if you +want your binaries to run on older versions of the same OS. If your +program is mostly built from source, don't bother. ### Why? @@ -32,10 +31,6 @@ s/ent\_//g on all the call sites and discard this shim. This project began because [Urbit](https://github.com/urbit/urbit)'s entropy-generation function was bothering me. Then it got out of hand. -### What about Windows? - -I'm happy to receive donations or pull requests. - ### References * [OpenBSD getentropy](https://man.openbsd.org/cgi-bin/man.cgi/OpenBSD-current/man2/getentropy.2) diff --git a/ent.c b/ent.c deleted file mode 100644 index 425625187..000000000 --- a/ent.c +++ /dev/null @@ -1,72 +0,0 @@ -#include - -/* ent.h undefs all constants and config.h is #pragma once. */ - -#if defined(ENT_GETRANDOM) - -#define ENT_IMPL -#define _GNU_SOURCE -#include -#include - -#define ENT_DEFS (void)0 -#define ENT_INIT() (void)0 -#define ENT_READ(B, L) syscall(SYS_getrandom, B, L, 0) -#define ENT_FINI() (void)0 - -#elif defined(ENT_URANDOM) - -#define ENT_IMPL -#include -#include -#include -#include - -#define ENT_DEFS int fd -#define ENT_INIT() do { \ - if ((fd = open("/dev/urandom", O_RDONLY)) < 0) \ - return -1; \ -} while (0) -#define ENT_READ(B, L) read(fd, B, L) -#define ENT_FINI() (void) close(fd) - -#endif - - -#include - -#if defined(ENT_IMPL) - -#include -#include - - -int -ent_getentropy(void* buf, size_t len) -{ - char *cuf = buf; - int ret; - ENT_DEFS; - - assert(len <= 256); - if (!len) - return 0; - ENT_INIT(); - while (len && (ret = ENT_READ(cuf, len)) != 0) { - if (ret < 0) { - if (errno == EINTR) - continue; - break; - } - len -= ret; - cuf += ret; - } - ENT_FINI(); - if (!ret) { - ret = -1; - errno = EIO; - } - return ret < 0 ? ret : 0; -} - -#endif /* ENT_IMPL */ diff --git a/include/ent.h b/include/ent.h new file mode 100644 index 000000000..f06b14ea1 --- /dev/null +++ b/include/ent.h @@ -0,0 +1,34 @@ +/* Copyright 2019 Steven Dee. All rights reserved. +** +** Permission is hereby granted, free of charge, to any person obtaining +** a copy of this software and associated documentation files (the +** "Software"), to deal in the Software without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Software, and to +** permit persons to whom the Software is furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ +#pragma once + +#include + +/* Fills buf with high-quality entropy. +** +** buflen is the number of bytes, no greater than 256. +** +** Returns 0 on success. On failure, returns -1 and sets errno to +** indicate the error. +*/ +int +ent_getentropy(void* buf, size_t buflen); diff --git a/include/ent/ent.h b/include/ent/ent.h deleted file mode 100644 index 03d4ee6e5..000000000 --- a/include/ent/ent.h +++ /dev/null @@ -1,59 +0,0 @@ -/* Copyright 2018 Steven Dee. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -#pragma once - -#include - -#include - -#if defined(ENT_GETENTROPY) -# if defined(ENT_GE_SYSRANDOM) -# include /* OSX sys/random.h needs Availability.h from this */ -# include -# elif defined(ENT_GE_UNISTD) -# include -# else -# error "libent: this shouldn't happen" -# endif -# define ent_getentropy getentropy -#elif defined(ENT_GETRANDOM) || defined(ENT_URANDOM) - -/* Fills buf with high-quality entropy. - * - * buflen is the number of bytes, no greater than 256. - * - * Returns 0 on success. On failure, returns -1 and sets errno to - * indicate the error. - */ -int -ent_getentropy(void* buf, size_t buflen); - -#else -# error "libent: platform not supported" -#endif - -#undef ENT_GETENTROPY -#undef ENT_GE_SYSRANDOM -#undef ENT_GE_UNISTD -#undef ENT_GETRANDOM -#undef ENT_URANDOM diff --git a/include/meson.build b/include/meson.build new file mode 100644 index 000000000..35d213df0 --- /dev/null +++ b/include/meson.build @@ -0,0 +1 @@ +#install_headers('ent.h') # XX uncomment to install locally diff --git a/meson.build b/meson.build index bba9682e8..3b5cc7bb4 100644 --- a/meson.build +++ b/meson.build @@ -1,22 +1,10 @@ -project('libent', 'c', - default_options : ['c_std=c99', 'cpp_std=c++11'], - version : '0.0.1', - license : 'MIT') - -subdir('include/ent') +project('libent', 'c', version: '0.1.0', license: 'MIT') inc = include_directories('include') -ent_sources = ['ent.c'] - -libent = static_library('ent', - sources : ent_sources, - include_directories : inc, - c_args : ['-Wall', '-pedantic'], - install : false) - -libent_dep = declare_dependency(include_directories : inc, link_with : libent) +subdir('include') +subdir('src') ent_sample = executable('sample', ['sample.c'], - dependencies : [libent_dep]) + dependencies: [libent_dep]) diff --git a/meson_options.txt b/meson_options.txt index 54379955b..036dde9b3 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -1,2 +1,2 @@ -option('support-older-oses', type : 'boolean', value : false, +option('ent_compat', type : 'boolean', value : false, description : 'Tries to work on older systems. Useful for binary releases. (Uses getrandom on Linux, /dev/urandom on other *nix.)') diff --git a/sample.c b/sample.c index 881a0df2a..abd5ad281 100644 --- a/sample.c +++ b/sample.c @@ -2,7 +2,7 @@ #include #include -#include +#include int diff --git a/src/ent.c b/src/ent.c new file mode 100644 index 000000000..2e31f47f4 --- /dev/null +++ b/src/ent.c @@ -0,0 +1,73 @@ +#include +#include "config.h" + +#if defined(ENT_GETENTROPY) +# include +# if defined(ENT_GE_SYSRANDOM) +# include +# endif + + int + ent_getentropy(void* buf, size_t len) + { + return getentropy(buf, len); + } + +#elif defined(ENT_IMPL) +# include +# include +# if defined(ENT_GETRANDOM) +# define _GNU_SOURCE +# include +# include + +# define ENT_DEFS (void)0 +# define ENT_INIT() (void)0 +# define ENT_READ(B, L) syscall(SYS_getrandom, B, L, 0) +# define ENT_FINI() (void)0 +# elif defined(ENT_URANDOM) +# include +# include +# include +# include + +# define ENT_DEFS int fd +# define ENT_INIT() do { \ + if ((fd = open("/dev/urandom", O_RDONLY)) < 0) \ + return -1; \ + } while (0) +# define ENT_READ(B, L) read(fd, B, L) +# define ENT_FINI() (void) close(fd) +# endif + + int + ent_getentropy(void* buf, size_t len) + { + char *cuf = buf; + int ret; + ENT_DEFS; + + assert(len <= 256); + if (!len) + return 0; + ENT_INIT(); + while (len && (ret = ENT_READ(cuf, len)) != 0) { + if (ret < 0) { + if (errno == EINTR) + continue; + break; + } + len -= ret; + cuf += ret; + } + ENT_FINI(); + if (!ret) { + ret = -1; + errno = EIO; + } + return ret < 0 ? ret : 0; + } + +#else +# error "libent: platform not supported" +#endif diff --git a/include/ent/meson.build b/src/meson.build similarity index 50% rename from include/ent/meson.build rename to src/meson.build index e4bd4e17a..ae611d145 100644 --- a/include/ent/meson.build +++ b/src/meson.build @@ -1,22 +1,21 @@ conf_data = configuration_data() compiler = meson.get_compiler('c') -older_oses = get_option('support-older-oses') +compat = get_option('ent_compat') -if not older_oses +if not compat code = '''#include - #include /* OSX sys/random.h needs Availability.h from this */ + #include #include int main() { return getentropy((void*)0, 0); } ''' - sysrandom = compiler.links(code, name : 'getentropy in sys/random.h') + sysrandom = compiler.links(code, name: 'getentropy in sys/random.h') conf_data.set('ENT_GE_SYSRANDOM', sysrandom) if not sysrandom code = '''#include int main() { return getentropy((void*)0, 0); } ''' - unistd = compiler.links(code, name : 'getentropy is in unistd.h') - conf_data.set('ENT_GE_UNISTD', unistd) + unistd = compiler.links(code, name: 'getentropy in unistd.h') endif have_getentropy = sysrandom or unistd conf_data.set('ENT_GETENTROPY', have_getentropy) @@ -31,18 +30,29 @@ if not have_getentropy #include int main() { return !syscall(SYS_getrandom, (void*)0, 0, 0); } ''' - getrandom = compiler.links(code, name : 'getrandom syscall available') + getrandom = compiler.links(code, name: 'getrandom syscall available') conf_data.set('ENT_GETRANDOM', getrandom) if not getrandom code = '''#include int main() { return open("/dev/urandom", O_RDONLY) >= 0 ? 0 : 1; } ''' - urandom = compiler.run(code, name : 'can open /dev/urandom').returncode() == 0 + urandom = compiler.run(code, name: 'can open /dev/urandom').returncode() == 0 conf_data.set('ENT_URANDOM', urandom) endif + ent_impl = getrandom or urandom + conf_data.set('ENT_IMPL', ent_impl) endif -configure_file(output : 'config.h', - configuration : conf_data) +config_file = configure_file(output: 'config.h', + configuration: conf_data) + +ent_sources = ['ent.c', config_file] + +libent = static_library('ent', ent_sources, + include_directories: inc, + c_args: ['-Wall', '-pedantic'], + install: false) # XX set to true to install locally + +libent_dep = declare_dependency(include_directories: inc, link_with: libent) From 4b5e644e8f019aef0ca173f30325e2facd3cc29a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C5=8Dshin?= Date: Wed, 2 Jan 2019 10:14:32 -0800 Subject: [PATCH 30/43] Special case OpenBSD --- src/meson.build | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/meson.build b/src/meson.build index ae611d145..08c81d756 100644 --- a/src/meson.build +++ b/src/meson.build @@ -1,6 +1,7 @@ conf_data = configuration_data() compiler = meson.get_compiler('c') -compat = get_option('ent_compat') +# OpenBSD has had getentropy since 5.6. It's fine. +compat = get_option('ent_compat') and host_machine.system() != 'openbsd' if not compat code = '''#include From 95ebac80939a5b1cd2833257e76dfab1e6d0004f Mon Sep 17 00:00:00 2001 From: Steven Dee Date: Wed, 2 Jan 2019 12:57:37 -0800 Subject: [PATCH 31/43] Update README.md --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 511037f31..e6a56ee49 100644 --- a/README.md +++ b/README.md @@ -9,11 +9,11 @@ It uses meson. `meson ./build && ninja -C build` should do the trick. #### Build options -It has one option, `support-older-oses`, which tells it to be -conservative. On Linux, this means using `getrandom` directly; on other -\*nix, it means reading from `/dev/urandom`. This may make sense if you -want your binaries to run on older versions of the same OS. If your -program is mostly built from source, don't bother. +It has one option, `ent_compat`, which tells it to be conservative. On +Linux, this means using `getrandom` directly; on other \*nix, it means +reading from `/dev/urandom`. This may make sense if you want your +binaries to run on older versions of the same OS. If your program is +mostly built from source, don't bother. ### Why? From 8ce0600e0010c011f551d50ec1ae989a795ee756 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C5=8Dshin?= Date: Wed, 2 Jan 2019 13:57:06 -0800 Subject: [PATCH 32/43] Simplify by using stdio Their read loop is probably better anyway. This also sets CLOEXEC on the opened file, since who knows. We can do this in the getrandom case since on small reads (len <= 256), getrandom doesn't fail with EINTR. --- meson.build | 2 +- src/ent.c | 41 ++++++++++++----------------------------- src/meson.build | 4 ++-- 3 files changed, 15 insertions(+), 32 deletions(-) diff --git a/meson.build b/meson.build index 3b5cc7bb4..174486e3c 100644 --- a/meson.build +++ b/meson.build @@ -1,4 +1,4 @@ -project('libent', 'c', version: '0.1.0', license: 'MIT') +project('libent', 'c', version: '0.1.1', license: 'MIT') inc = include_directories('include') diff --git a/src/ent.c b/src/ent.c index 2e31f47f4..c628f579b 100644 --- a/src/ent.c +++ b/src/ent.c @@ -20,52 +20,35 @@ # define _GNU_SOURCE # include # include - # define ENT_DEFS (void)0 # define ENT_INIT() (void)0 # define ENT_READ(B, L) syscall(SYS_getrandom, B, L, 0) # define ENT_FINI() (void)0 # elif defined(ENT_URANDOM) -# include -# include -# include -# include - -# define ENT_DEFS int fd -# define ENT_INIT() do { \ - if ((fd = open("/dev/urandom", O_RDONLY)) < 0) \ - return -1; \ +# include +# define ENT_DEFS FILE *f +# define ENT_INIT() do { \ + if (!(f = fopen("/dev/urandom", "re"))) \ + return -1; \ } while (0) -# define ENT_READ(B, L) read(fd, B, L) -# define ENT_FINI() (void) close(fd) +# define ENT_READ(B, L) fread(B, 1, L, f) +# define ENT_FINI() (void) fclose(f) # endif int ent_getentropy(void* buf, size_t len) { - char *cuf = buf; - int ret; ENT_DEFS; assert(len <= 256); - if (!len) - return 0; ENT_INIT(); - while (len && (ret = ENT_READ(cuf, len)) != 0) { - if (ret < 0) { - if (errno == EINTR) - continue; - break; - } - len -= ret; - cuf += ret; + if (len != ENT_READ(buf, len)) { + ENT_FINI(); + errno = EIO; + return -1; } ENT_FINI(); - if (!ret) { - ret = -1; - errno = EIO; - } - return ret < 0 ? ret : 0; + return 0; } #else diff --git a/src/meson.build b/src/meson.build index 08c81d756..04fe34f78 100644 --- a/src/meson.build +++ b/src/meson.build @@ -35,8 +35,8 @@ if not have_getentropy conf_data.set('ENT_GETRANDOM', getrandom) if not getrandom - code = '''#include - int main() { return open("/dev/urandom", O_RDONLY) >= 0 ? 0 : 1; } + code = '''#include + int main() { return fopen("/dev/urandom", "r") ? 0 : 1; } ''' urandom = compiler.run(code, name: 'can open /dev/urandom').returncode() == 0 conf_data.set('ENT_URANDOM', urandom) From 1f0e431259990c7601fc8815212f9aba437eb4f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C5=8Dshin?= Date: Wed, 2 Jan 2019 15:36:02 -0800 Subject: [PATCH 33/43] Remove assert, add _ent_fail --- meson.build | 2 +- src/ent.c | 20 +++++++++++++------- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/meson.build b/meson.build index 174486e3c..248096add 100644 --- a/meson.build +++ b/meson.build @@ -1,4 +1,4 @@ -project('libent', 'c', version: '0.1.1', license: 'MIT') +project('libent', 'c', version: '0.1.2', license: 'MIT') inc = include_directories('include') diff --git a/src/ent.c b/src/ent.c index c628f579b..106cc25c3 100644 --- a/src/ent.c +++ b/src/ent.c @@ -14,7 +14,6 @@ } #elif defined(ENT_IMPL) -# include # include # if defined(ENT_GETRANDOM) # define _GNU_SOURCE @@ -35,19 +34,26 @@ # define ENT_FINI() (void) fclose(f) # endif + static int + _ent_fail() + { + errno = EIO; + return -1; + } + int ent_getentropy(void* buf, size_t len) { + int r; ENT_DEFS; - assert(len <= 256); + if (len > 256) + return _ent_fail(); ENT_INIT(); - if (len != ENT_READ(buf, len)) { - ENT_FINI(); - errno = EIO; - return -1; - } + r = ENT_READ(buf, len); ENT_FINI(); + if (r != len) + return _ent_fail(); return 0; } From 7506fb31577fc5e185b31ed9f6ce6072e3f20637 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C5=8Dshin?= Date: Wed, 2 Jan 2019 16:22:19 -0800 Subject: [PATCH 34/43] Minor cleanup --- meson.build | 5 ++--- src/ent.c | 29 ++++++++++++++--------------- 2 files changed, 16 insertions(+), 18 deletions(-) diff --git a/meson.build b/meson.build index 248096add..ad879ba37 100644 --- a/meson.build +++ b/meson.build @@ -1,10 +1,9 @@ -project('libent', 'c', version: '0.1.2', license: 'MIT') +project('libent', 'c', version: '0.1.3', license: 'MIT') inc = include_directories('include') subdir('include') subdir('src') -ent_sample = executable('sample', - ['sample.c'], +ent_sample = executable('sample', ['sample.c'], dependencies: [libent_dep]) diff --git a/src/ent.c b/src/ent.c index 106cc25c3..f084adb4b 100644 --- a/src/ent.c +++ b/src/ent.c @@ -19,19 +19,8 @@ # define _GNU_SOURCE # include # include -# define ENT_DEFS (void)0 -# define ENT_INIT() (void)0 -# define ENT_READ(B, L) syscall(SYS_getrandom, B, L, 0) -# define ENT_FINI() (void)0 # elif defined(ENT_URANDOM) # include -# define ENT_DEFS FILE *f -# define ENT_INIT() do { \ - if (!(f = fopen("/dev/urandom", "re"))) \ - return -1; \ - } while (0) -# define ENT_READ(B, L) fread(B, 1, L, f) -# define ENT_FINI() (void) fclose(f) # endif static int @@ -45,13 +34,23 @@ ent_getentropy(void* buf, size_t len) { int r; - ENT_DEFS; if (len > 256) return _ent_fail(); - ENT_INIT(); - r = ENT_READ(buf, len); - ENT_FINI(); +# if defined(ENT_GETRANDOM) + r = syscall(SYS_getrandom, buf, len, 0); + if (r < 0) + return r; +# elif defined(ENT_URANDOM) + { + FILE *f; + + if (!(f = fopen("/dev/urandom", "re"))) + return -1; + r = fread(buf, 1, len, f); + (void) fclose(f); + } +# endif if (r != len) return _ent_fail(); return 0; From 1d325649b99dd2f6aef35a7d2a4fd0ac006e79d7 Mon Sep 17 00:00:00 2001 From: Benjamin Summers Date: Wed, 16 Jan 2019 15:23:46 -0800 Subject: [PATCH 35/43] Wrote a config.h.in file for old meson versions. --- src/config.h.in | 3 +++ src/meson.build | 7 +++++-- 2 files changed, 8 insertions(+), 2 deletions(-) create mode 100644 src/config.h.in diff --git a/src/config.h.in b/src/config.h.in new file mode 100644 index 000000000..845de4cde --- /dev/null +++ b/src/config.h.in @@ -0,0 +1,3 @@ +#pragma once +#mesondefine ENT_GETENTROPY +#mesondefine ENT_GE_SYSRANDOM diff --git a/src/meson.build b/src/meson.build index 04fe34f78..8dd73b680 100644 --- a/src/meson.build +++ b/src/meson.build @@ -46,8 +46,11 @@ if not have_getentropy endif -config_file = configure_file(output: 'config.h', - configuration: conf_data) +config_file = configure_file( + output: 'config.h', + input: 'config.h.in', + configuration: conf_data, +) ent_sources = ['ent.c', config_file] From 3e1ccc3b101f08b0fc56bfb945dbd7002df49fc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C5=8Dshin?= Date: Wed, 16 Jan 2019 17:23:10 -0800 Subject: [PATCH 36/43] Add all config vars to config.h.in --- src/config.h.in | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/config.h.in b/src/config.h.in index 845de4cde..785c41524 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -1,3 +1,6 @@ #pragma once #mesondefine ENT_GETENTROPY #mesondefine ENT_GE_SYSRANDOM +#mesondefine ENT_GETRANDOM +#mesondefine ENT_URANDOM +#mesondefine ENT_IMPL From 76251f6b4c82e44f5b14a5861ca8d9b66b2ed230 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C5=8Dshin?= Date: Wed, 16 Jan 2019 17:28:53 -0800 Subject: [PATCH 37/43] v0.1.4 --- meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meson.build b/meson.build index ad879ba37..3a911908d 100644 --- a/meson.build +++ b/meson.build @@ -1,4 +1,4 @@ -project('libent', 'c', version: '0.1.3', license: 'MIT') +project('libent', 'c', version: '0.1.4', license: 'MIT') inc = include_directories('include') From 950b19cad8e49c496228404a83928f020c1b764f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C5=8Dshin?= Date: Thu, 17 Jan 2019 15:48:49 -0800 Subject: [PATCH 38/43] v0.2.0 - ent_install option to install locally (defaults to false.) - Add pkg-config info if we're installing (hence the minor version bump.) - Remove ENT_IMPL, making the preprocessor logic in ent.c more foolproof. - Change meson.build style around a bit. --- README.md | 24 +++++++++++++++--------- include/meson.build | 4 +++- meson.build | 23 ++++++++++++++++++++--- meson_options.txt | 4 +++- src/config.h.in | 1 - src/ent.c | 6 +++--- src/meson.build | 26 ++++++++++++-------------- 7 files changed, 56 insertions(+), 32 deletions(-) diff --git a/README.md b/README.md index e6a56ee49..189a2c32e 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,25 @@ libent is a cross-platform wrapper around `getentropy(2)`. It exports -one symbol, `ent_getentropy`. If `getentropy` is available, then it's -just a shim around that. Otherwise, it uses `getrandom(2)` (available -since kernel 3.17) on Linux, or `/dev/urandom` on other \*nix. +one symbol, `ent_getentropy`. If getentropy is available, then it's just +a shim around that. Otherwise, it uses `getrandom(2)` (available since +kernel 3.17) on Linux, or `/dev/urandom` on other \*nix. ### Building It uses meson. `meson ./build && ninja -C build` should do the trick. -#### Build options +The main intended way to use this library is to depend on it from +another meson project, i.e., to pull `libent_dep` out from this library +as a [subproject](https://mesonbuild.com/Subprojects.html). It's also +possible to install it as a regular library if you want to for some +reason — just run meson with `-Dent_install=true` and add on a `sudo +ninja -C build install`. -It has one option, `ent_compat`, which tells it to be conservative. On -Linux, this means using `getrandom` directly; on other \*nix, it means -reading from `/dev/urandom`. This may make sense if you want your -binaries to run on older versions of the same OS. If your program is -mostly built from source, don't bother. +If you want to release a binary distribution of your program, you may +want to build with `-Dent_compat=true`. This tells libent not to try to +use getentropy, which might result in a program that can run against +an older libc version on some platforms. (`ent_compat` does nothing on +OpenBSD; we claim that 5.6 is old enough for anyone's purposes who wants +to use this library.) ### Why? diff --git a/include/meson.build b/include/meson.build index 35d213df0..3bac4c30c 100644 --- a/include/meson.build +++ b/include/meson.build @@ -1 +1,3 @@ -#install_headers('ent.h') # XX uncomment to install locally +if get_option('ent_install') + install_headers('ent.h') +endif diff --git a/meson.build b/meson.build index 3a911908d..1fed79bb6 100644 --- a/meson.build +++ b/meson.build @@ -1,9 +1,26 @@ -project('libent', 'c', version: '0.1.4', license: 'MIT') +project('libent', 'c', version: '0.2.0', license: 'MIT') inc = include_directories('include') subdir('include') subdir('src') -ent_sample = executable('sample', ['sample.c'], - dependencies: [libent_dep]) +libent_dep = declare_dependency( + include_directories: inc, + link_with: libent, +) + +ent_sample = executable( + 'sample', + ['sample.c'], + dependencies: [libent_dep], +) + +if get_option('ent_install') + pkg = import('pkgconfig') + pkg.generate( + libraries: [libent], + name: 'libent', + description: 'getentropy shim', + ) +endif diff --git a/meson_options.txt b/meson_options.txt index 036dde9b3..ef45b64da 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -1,2 +1,4 @@ option('ent_compat', type : 'boolean', value : false, - description : 'Tries to work on older systems. Useful for binary releases. (Uses getrandom on Linux, /dev/urandom on other *nix.)') + description : 'Don\'t rely on system getentropy') +option('ent_install', type : 'boolean', value : false, + description : 'Install locally') diff --git a/src/config.h.in b/src/config.h.in index 785c41524..8ed218c87 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -3,4 +3,3 @@ #mesondefine ENT_GE_SYSRANDOM #mesondefine ENT_GETRANDOM #mesondefine ENT_URANDOM -#mesondefine ENT_IMPL diff --git a/src/ent.c b/src/ent.c index f084adb4b..57d437941 100644 --- a/src/ent.c +++ b/src/ent.c @@ -13,13 +13,13 @@ return getentropy(buf, len); } -#elif defined(ENT_IMPL) +#elif defined(ENT_GETRANDOM) || defined(ENT_URANDOM) # include # if defined(ENT_GETRANDOM) # define _GNU_SOURCE # include # include -# elif defined(ENT_URANDOM) +# else # include # endif @@ -41,7 +41,7 @@ r = syscall(SYS_getrandom, buf, len, 0); if (r < 0) return r; -# elif defined(ENT_URANDOM) +# else { FILE *f; diff --git a/src/meson.build b/src/meson.build index 8dd73b680..03f3b1550 100644 --- a/src/meson.build +++ b/src/meson.build @@ -1,5 +1,5 @@ conf_data = configuration_data() -compiler = meson.get_compiler('c') +cc = meson.get_compiler('c') # OpenBSD has had getentropy since 5.6. It's fine. compat = get_option('ent_compat') and host_machine.system() != 'openbsd' @@ -9,14 +9,14 @@ if not compat #include int main() { return getentropy((void*)0, 0); } ''' - sysrandom = compiler.links(code, name: 'getentropy in sys/random.h') + sysrandom = cc.links(code, name: 'getentropy in sys/random.h') conf_data.set('ENT_GE_SYSRANDOM', sysrandom) if not sysrandom code = '''#include int main() { return getentropy((void*)0, 0); } ''' - unistd = compiler.links(code, name: 'getentropy in unistd.h') + unistd = cc.links(code, name: 'getentropy in unistd.h') endif have_getentropy = sysrandom or unistd conf_data.set('ENT_GETENTROPY', have_getentropy) @@ -31,21 +31,18 @@ if not have_getentropy #include int main() { return !syscall(SYS_getrandom, (void*)0, 0, 0); } ''' - getrandom = compiler.links(code, name: 'getrandom syscall available') + getrandom = cc.links(code, name: 'getrandom syscall available') conf_data.set('ENT_GETRANDOM', getrandom) if not getrandom code = '''#include int main() { return fopen("/dev/urandom", "r") ? 0 : 1; } ''' - urandom = compiler.run(code, name: 'can open /dev/urandom').returncode() == 0 + urandom = cc.run(code, name: 'can open /dev/urandom').returncode() == 0 conf_data.set('ENT_URANDOM', urandom) endif - ent_impl = getrandom or urandom - conf_data.set('ENT_IMPL', ent_impl) endif - config_file = configure_file( output: 'config.h', input: 'config.h.in', @@ -54,9 +51,10 @@ config_file = configure_file( ent_sources = ['ent.c', config_file] -libent = static_library('ent', ent_sources, - include_directories: inc, - c_args: ['-Wall', '-pedantic'], - install: false) # XX set to true to install locally - -libent_dep = declare_dependency(include_directories: inc, link_with: libent) +libent = static_library( + 'ent', + ent_sources, + include_directories: inc, + c_args: ['-Wall', '-pedantic'], + install: get_option('ent_install'), +) From bc607bdfa06a6781d4865b8b1ce46ce17d0fe6e6 Mon Sep 17 00:00:00 2001 From: Adam Bliss Date: Thu, 17 Jan 2019 23:02:22 -0500 Subject: [PATCH 39/43] Actually try calling getrandom while configuring --- src/meson.build | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/meson.build b/src/meson.build index 03f3b1550..160fbdc98 100644 --- a/src/meson.build +++ b/src/meson.build @@ -29,9 +29,9 @@ if not have_getentropy #include #include #include - int main() { return !syscall(SYS_getrandom, (void*)0, 0, 0); } + int main() { return !(syscall(SYS_getrandom, (void*)0, 0, 0) >= 0); } ''' - getrandom = cc.links(code, name: 'getrandom syscall available') + getrandom = cc.run(code, name: 'getrandom syscall available').returncode() == 0 conf_data.set('ENT_GETRANDOM', getrandom) if not getrandom From d95464622e574578ca5d696846b7b77fb29c9359 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C5=8Dshin?= Date: Fri, 18 Jan 2019 08:35:57 -0800 Subject: [PATCH 40/43] Version bump, remove double negative I almost would rather say syscall(...) == 0 ? 0 : 1, but decided not to. --- meson.build | 2 +- src/meson.build | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/meson.build b/meson.build index 1fed79bb6..01d703915 100644 --- a/meson.build +++ b/meson.build @@ -1,4 +1,4 @@ -project('libent', 'c', version: '0.2.0', license: 'MIT') +project('libent', 'c', version: '0.2.1', license: 'MIT') inc = include_directories('include') diff --git a/src/meson.build b/src/meson.build index 160fbdc98..efe1d5d24 100644 --- a/src/meson.build +++ b/src/meson.build @@ -29,7 +29,7 @@ if not have_getentropy #include #include #include - int main() { return !(syscall(SYS_getrandom, (void*)0, 0, 0) >= 0); } + int main() { return syscall(SYS_getrandom, (void*)0, 0, 0); } ''' getrandom = cc.run(code, name: 'getrandom syscall available').returncode() == 0 conf_data.set('ENT_GETRANDOM', getrandom) From 659aaed38c52816a931584d0bdf0a641ebe013dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C5=8Dshin?= Date: Fri, 18 Jan 2019 08:47:42 -0800 Subject: [PATCH 41/43] Clarify README comment --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 189a2c32e..ef6fabe6f 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,8 @@ want to build with `-Dent_compat=true`. This tells libent not to try to use getentropy, which might result in a program that can run against an older libc version on some platforms. (`ent_compat` does nothing on OpenBSD; we claim that 5.6 is old enough for anyone's purposes who wants -to use this library.) +to use this library. If you want it to work on older systems, compile it +against them.) ### Why? From 4116879b9e39e6c9963272942ae4635ffdbc1629 Mon Sep 17 00:00:00 2001 From: Benjamin Summers Date: Fri, 1 Feb 2019 16:10:43 -0800 Subject: [PATCH 42/43] Meson tries to hard to be "smart". Replaced with a Makefile. --- .gitignore | 5 +++- Makefile | 29 +++++++++++++++++++++ README.md | 48 +++++++++++++++++++++++------------ configure | 3 +++ ent.c | 62 +++++++++++++++++++++++++++++++++++++++++++++ ent.h | 13 ++++++++++ include/ent.h | 34 ------------------------- include/meson.build | 3 --- meson.build | 26 ------------------- meson_options.txt | 4 --- sample.c | 24 ------------------ src/config.h.in | 5 ---- src/ent.c | 61 -------------------------------------------- src/meson.build | 60 ------------------------------------------- test.c | 20 +++++++++++++++ 15 files changed, 163 insertions(+), 234 deletions(-) create mode 100644 Makefile create mode 100755 configure create mode 100644 ent.c create mode 100644 ent.h delete mode 100644 include/ent.h delete mode 100644 include/meson.build delete mode 100644 meson.build delete mode 100644 meson_options.txt delete mode 100644 sample.c delete mode 100644 src/config.h.in delete mode 100644 src/ent.c delete mode 100644 src/meson.build create mode 100644 test.c diff --git a/.gitignore b/.gitignore index 796b96d1c..97b75b05e 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,4 @@ -/build +/*.a +/*.o +/out +/test diff --git a/Makefile b/Makefile new file mode 100644 index 000000000..c03478c26 --- /dev/null +++ b/Makefile @@ -0,0 +1,29 @@ +CC ?= cc +AR ?= ar +PREFIX ?= ./out + +ifndef IMPL +$(error IMPL must be set) +endif + +################################################################################ + +.PHONY: all test install clean + +all: ent.c ent.h + $(CC) -D$(IMPL) -O3 -Wall -pedantic -std=gnu99 -c ent.c + $(AR) rcs ent.a ent.o + +test: all + $(CC) -D$(IMPL) -O3 -Wall -pedantic -std=gnu99 ent.c test.c -o test + ./test + +install: all + @mkdir -p $(PREFIX)/lib/ + @mkdir -p $(PREFIX)/include/ + cp ent.a $(PREFIX)/lib/ + cp ent.h $(PREFIX)/include/ + +clean: + rm -f *.o *.a test + rm -rf ./out diff --git a/README.md b/README.md index ef6fabe6f..6ab9f5417 100644 --- a/README.md +++ b/README.md @@ -1,26 +1,41 @@ -libent is a cross-platform wrapper around `getentropy(2)`. It exports +## `libent` + +`libent` is a cross-platform wrapper around `getentropy(2)`. It exports one symbol, `ent_getentropy`. If getentropy is available, then it's just a shim around that. Otherwise, it uses `getrandom(2)` (available since kernel 3.17) on Linux, or `/dev/urandom` on other \*nix. -### Building -It uses meson. `meson ./build && ninja -C build` should do the trick. +### Building and Testing -The main intended way to use this library is to depend on it from -another meson project, i.e., to pull `libent_dep` out from this library -as a [subproject](https://mesonbuild.com/Subprojects.html). It's also -possible to install it as a regular library if you want to for some -reason — just run meson with `-Dent_install=true` and add on a `sudo -ninja -C build install`. +To build, set the `IMPL` variable to one of the folling values, and run +`make`. + +- `ENT_DEV_URANDOM` +- `ENT_GETENTROPY_UNISTD` +- `ENT_GETENTROPY_SYSRANDOM` +- `ENT_GETRANDOM` + +For example: + +```bash +export IMPL=ENT_GETENTROPY_SYSRANDOM +make +make test +``` + + +### Installing + +To install, you'll need to set `PREFIX` to where you want this to be +installed. + +```bash +export PREFIX=/usr/local +export IMPL=ENT_GETENTROPY_SYSRANDOM +make install +``` -If you want to release a binary distribution of your program, you may -want to build with `-Dent_compat=true`. This tells libent not to try to -use getentropy, which might result in a program that can run against -an older libc version on some platforms. (`ent_compat` does nothing on -OpenBSD; we claim that 5.6 is old enough for anyone's purposes who wants -to use this library. If you want it to work on older systems, compile it -against them.) ### Why? @@ -38,6 +53,7 @@ s/ent\_//g on all the call sites and discard this shim. This project began because [Urbit](https://github.com/urbit/urbit)'s entropy-generation function was bothering me. Then it got out of hand. + ### References * [OpenBSD getentropy](https://man.openbsd.org/cgi-bin/man.cgi/OpenBSD-current/man2/getentropy.2) diff --git a/configure b/configure new file mode 100755 index 000000000..817d3a2cf --- /dev/null +++ b/configure @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +sed -i 's|$(error IMPL must be set)|IMPL=ENT_DEV_URANDOM|' Makefile diff --git a/ent.c b/ent.c new file mode 100644 index 000000000..7aee7f48d --- /dev/null +++ b/ent.c @@ -0,0 +1,62 @@ +// Use `getentropy` from unistd.h ////////////////////////////////////////////// + +#if defined(ENT_GETENTROPY_UNISTD) +#include +#include +int ent_getentropy(void* buf, size_t len) { + return getentropy(buf, len); +} + + +// Use `getentropy` from sys/random.h ////////////////////////////////////////// + +#elif defined(ENT_GETENTROPY_SYSRANDOM) +#include +#include +int ent_getentropy(void* buf, size_t len) { + return getentropy(buf, len); +} + + +// Use the `getrandom` syscall ///////////////////////////////////////////////// + +#elif defined(ENT_GETRANDOM_SYSCALL) +#include +#include +#define _GNU_SOURCE +#include +#include + +#define ENTFAIL { errno=EIO; return -1; } + +int ent_getentropy(void* buf, size_t len) { + if (len > 256) ENTFAIL + int r = syscall(SYS_getrandom, buf, len, 0); + if (r < 0) return r; + if (r != len) ENTFAIL + return 0; +} + + +// Use `/dev/urandom` ////////////////////////////////////////////////////////// + +#elif defined(ENT_DEV_URANDOM) +#include +#include +#include + +#define ENTFAIL { errno=EIO; return -1; } + +int ent_getentropy(void* buf, size_t len) { + if (len > 256) ENTFAIL; + FILE *f = fopen("/dev/urandom", "re"); + if (!f) return -1; + int r = fread(buf, 1, len, f); + (void) fclose(f); + if (r != len) ENTFAIL + return 0; +} + +#else +#error "One of these must be set: ENT_DEV_URANDOM, ENT_GETENTROPY_UNISTD, ENT_GETENTROPY_SYSRANDOM, ENT_GETRANDOM_SYSCALL" +#endif diff --git a/ent.h b/ent.h new file mode 100644 index 000000000..e838d61b5 --- /dev/null +++ b/ent.h @@ -0,0 +1,13 @@ +#pragma once + +#include + +/* + Fills buf with high-quality entropy. + + buflen is the number of bytes, no greater than 256. + + Returns 0 on success. On failure, returns -1 and sets errno to + indicate the error. +*/ +int ent_getentropy(void* buf, size_t buflen); diff --git a/include/ent.h b/include/ent.h deleted file mode 100644 index f06b14ea1..000000000 --- a/include/ent.h +++ /dev/null @@ -1,34 +0,0 @@ -/* Copyright 2019 Steven Dee. All rights reserved. -** -** Permission is hereby granted, free of charge, to any person obtaining -** a copy of this software and associated documentation files (the -** "Software"), to deal in the Software without restriction, including -** without limitation the rights to use, copy, modify, merge, publish, -** distribute, sublicense, and/or sell copies of the Software, and to -** permit persons to whom the Software is furnished to do so, subject to -** the following conditions: -** -** The above copyright notice and this permission notice shall be included -** in all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -** SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ -#pragma once - -#include - -/* Fills buf with high-quality entropy. -** -** buflen is the number of bytes, no greater than 256. -** -** Returns 0 on success. On failure, returns -1 and sets errno to -** indicate the error. -*/ -int -ent_getentropy(void* buf, size_t buflen); diff --git a/include/meson.build b/include/meson.build deleted file mode 100644 index 3bac4c30c..000000000 --- a/include/meson.build +++ /dev/null @@ -1,3 +0,0 @@ -if get_option('ent_install') - install_headers('ent.h') -endif diff --git a/meson.build b/meson.build deleted file mode 100644 index 01d703915..000000000 --- a/meson.build +++ /dev/null @@ -1,26 +0,0 @@ -project('libent', 'c', version: '0.2.1', license: 'MIT') - -inc = include_directories('include') - -subdir('include') -subdir('src') - -libent_dep = declare_dependency( - include_directories: inc, - link_with: libent, -) - -ent_sample = executable( - 'sample', - ['sample.c'], - dependencies: [libent_dep], -) - -if get_option('ent_install') - pkg = import('pkgconfig') - pkg.generate( - libraries: [libent], - name: 'libent', - description: 'getentropy shim', - ) -endif diff --git a/meson_options.txt b/meson_options.txt deleted file mode 100644 index ef45b64da..000000000 --- a/meson_options.txt +++ /dev/null @@ -1,4 +0,0 @@ -option('ent_compat', type : 'boolean', value : false, - description : 'Don\'t rely on system getentropy') -option('ent_install', type : 'boolean', value : false, - description : 'Install locally') diff --git a/sample.c b/sample.c deleted file mode 100644 index abd5ad281..000000000 --- a/sample.c +++ /dev/null @@ -1,24 +0,0 @@ -#include -#include -#include - -#include - - -int -main() -{ - char buf[256]; - int i; - - memset(buf, 0, sizeof(buf)); - if (0 != ent_getentropy(buf, sizeof(buf))) { - perror("getentropy"); - exit(1); - } - for (i = 0; i < sizeof buf; ++i) { - printf("%02hhx", buf[i]); - } - puts(""); - return 0; -} diff --git a/src/config.h.in b/src/config.h.in deleted file mode 100644 index 8ed218c87..000000000 --- a/src/config.h.in +++ /dev/null @@ -1,5 +0,0 @@ -#pragma once -#mesondefine ENT_GETENTROPY -#mesondefine ENT_GE_SYSRANDOM -#mesondefine ENT_GETRANDOM -#mesondefine ENT_URANDOM diff --git a/src/ent.c b/src/ent.c deleted file mode 100644 index 57d437941..000000000 --- a/src/ent.c +++ /dev/null @@ -1,61 +0,0 @@ -#include -#include "config.h" - -#if defined(ENT_GETENTROPY) -# include -# if defined(ENT_GE_SYSRANDOM) -# include -# endif - - int - ent_getentropy(void* buf, size_t len) - { - return getentropy(buf, len); - } - -#elif defined(ENT_GETRANDOM) || defined(ENT_URANDOM) -# include -# if defined(ENT_GETRANDOM) -# define _GNU_SOURCE -# include -# include -# else -# include -# endif - - static int - _ent_fail() - { - errno = EIO; - return -1; - } - - int - ent_getentropy(void* buf, size_t len) - { - int r; - - if (len > 256) - return _ent_fail(); -# if defined(ENT_GETRANDOM) - r = syscall(SYS_getrandom, buf, len, 0); - if (r < 0) - return r; -# else - { - FILE *f; - - if (!(f = fopen("/dev/urandom", "re"))) - return -1; - r = fread(buf, 1, len, f); - (void) fclose(f); - } -# endif - if (r != len) - return _ent_fail(); - return 0; - } - -#else -# error "libent: platform not supported" -#endif diff --git a/src/meson.build b/src/meson.build deleted file mode 100644 index efe1d5d24..000000000 --- a/src/meson.build +++ /dev/null @@ -1,60 +0,0 @@ -conf_data = configuration_data() -cc = meson.get_compiler('c') -# OpenBSD has had getentropy since 5.6. It's fine. -compat = get_option('ent_compat') and host_machine.system() != 'openbsd' - -if not compat - code = '''#include - #include - #include - int main() { return getentropy((void*)0, 0); } - ''' - sysrandom = cc.links(code, name: 'getentropy in sys/random.h') - conf_data.set('ENT_GE_SYSRANDOM', sysrandom) - - if not sysrandom - code = '''#include - int main() { return getentropy((void*)0, 0); } - ''' - unistd = cc.links(code, name: 'getentropy in unistd.h') - endif - have_getentropy = sysrandom or unistd - conf_data.set('ENT_GETENTROPY', have_getentropy) -else - have_getentropy = false -endif - -if not have_getentropy - code = '''#define _GNU_SOURCE - #include - #include - #include - int main() { return syscall(SYS_getrandom, (void*)0, 0, 0); } - ''' - getrandom = cc.run(code, name: 'getrandom syscall available').returncode() == 0 - conf_data.set('ENT_GETRANDOM', getrandom) - - if not getrandom - code = '''#include - int main() { return fopen("/dev/urandom", "r") ? 0 : 1; } - ''' - urandom = cc.run(code, name: 'can open /dev/urandom').returncode() == 0 - conf_data.set('ENT_URANDOM', urandom) - endif -endif - -config_file = configure_file( - output: 'config.h', - input: 'config.h.in', - configuration: conf_data, -) - -ent_sources = ['ent.c', config_file] - -libent = static_library( - 'ent', - ent_sources, - include_directories: inc, - c_args: ['-Wall', '-pedantic'], - install: get_option('ent_install'), -) diff --git a/test.c b/test.c new file mode 100644 index 000000000..90b6ca0c6 --- /dev/null +++ b/test.c @@ -0,0 +1,20 @@ +#include +#include +#include + +#include "ent.h" + +int main(void) { + char buf[256] = {0}; + + if (0 != ent_getentropy(buf, sizeof(buf))) { + perror("getentropy"); + exit(1); + } + + for (int i = 0; i < sizeof buf; i++) { + printf("%02hhx", buf[i]); + } + + puts(""); +} From 31ac2913f14c6f7631f5792ad942605fb2d9fb87 Mon Sep 17 00:00:00 2001 From: Benjamin Summers Date: Fri, 1 Feb 2019 16:32:16 -0800 Subject: [PATCH 43/43] Wrote a really stupid configure script. --- Makefile | 8 ++++---- README.md | 26 ++------------------------ configure | 24 +++++++++++++++++++++++- 3 files changed, 29 insertions(+), 29 deletions(-) diff --git a/Makefile b/Makefile index c03478c26..88edb189e 100644 --- a/Makefile +++ b/Makefile @@ -11,17 +11,17 @@ endif .PHONY: all test install clean all: ent.c ent.h - $(CC) -D$(IMPL) -O3 -Wall -pedantic -std=gnu99 -c ent.c - $(AR) rcs ent.a ent.o + $(CC) -D$(IMPL) -O3 -Wall -Werror -pedantic -std=gnu99 -c ent.c + $(AR) rcs libent.a ent.o test: all - $(CC) -D$(IMPL) -O3 -Wall -pedantic -std=gnu99 ent.c test.c -o test + $(CC) -D$(IMPL) -O3 -Wall -Werror -pedantic -std=gnu99 ent.c test.c -o test ./test install: all @mkdir -p $(PREFIX)/lib/ @mkdir -p $(PREFIX)/include/ - cp ent.a $(PREFIX)/lib/ + cp libent.a $(PREFIX)/lib/ cp ent.h $(PREFIX)/include/ clean: diff --git a/README.md b/README.md index 6ab9f5417..e2bc1c7f5 100644 --- a/README.md +++ b/README.md @@ -8,35 +8,13 @@ kernel 3.17) on Linux, or `/dev/urandom` on other \*nix. ### Building and Testing -To build, set the `IMPL` variable to one of the folling values, and run -`make`. - -- `ENT_DEV_URANDOM` -- `ENT_GETENTROPY_UNISTD` -- `ENT_GETENTROPY_SYSRANDOM` -- `ENT_GETRANDOM` - -For example: - ```bash -export IMPL=ENT_GETENTROPY_SYSRANDOM +./configure make make test +PREFIX=/usr/local make install ``` - -### Installing - -To install, you'll need to set `PREFIX` to where you want this to be -installed. - -```bash -export PREFIX=/usr/local -export IMPL=ENT_GETENTROPY_SYSRANDOM -make install -``` - - ### Why? `getentropy` is the wave of the future. It's the correct API for diff --git a/configure b/configure index 817d3a2cf..3e98a5108 100755 --- a/configure +++ b/configure @@ -1,3 +1,25 @@ #!/usr/bin/env bash -sed -i 's|$(error IMPL must be set)|IMPL=ENT_DEV_URANDOM|' Makefile +log () { + echo "$@" >&2; +} + +for impl in ENT_GETENTROPY_UNISTD \ + ENT_GETENTROPY_SYSRANDOM \ + ENT_GETRANDOM_SYSCALL \ + ENT_DEV_URANDOM +do + export IMPL=$impl + + log "Trying IMPL=$IMPL" + + if IMPL=$impl make >/dev/null 2>/dev/null + then sed -i 's|$(error IMPL must be set)|IMPL='"$impl"'|' Makefile + log "IMPL=$IMPL works" + exit 0 + else log "IMPL=$IMPL failed" + fi +done + +log "This shouldn't happen, something is broken." +exit 1