From 6de837ba4e208260ac6043d521b0a1d79ffd58a7 Mon Sep 17 00:00:00 2001 From: Ondřej Surý Date: Tue, 30 Aug 2016 10:08:07 +0200 Subject: Use arc4random()/getrandom() to get random bytes instead of sysctl() interface --- src/openssl.c | 63 ++++++++++++++++++++++++++++++----------------------------- 1 file changed, 32 insertions(+), 31 deletions(-) (limited to 'src/openssl.c') diff --git a/src/openssl.c b/src/openssl.c index d8eebb5..6addcaa 100644 --- a/src/openssl.c +++ b/src/openssl.c @@ -48,6 +48,19 @@ #if __APPLE__ #include /* mach_absolute_time() */ +#define HAVE_ARC4RANDOM +#endif + +#if defined(__FreeBSD_kernel__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) +#define HAVE_ARC4RANDOM +#endif + +#if defined(__linux__) +#include +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0) +#define HAVE_GETRANDOM +#include +#endif #endif #include @@ -7811,44 +7824,16 @@ static struct randL_state *randL_getstate(lua_State *L) { return lua_touserdata(L, lua_upvalueindex(1)); } /* randL_getstate() */ -#ifndef HAVE_SYS_SYSCTL_H -#define HAVE_SYS_SYSCTL_H (BSD || __GLIBC__) -#endif - -#if HAVE_SYS_SYSCTL_H -#include /* CTL_KERN KERN_RANDOM RANDOM_UUID KERN_URND KERN_ARND sysctl(2) */ -#endif - -#ifndef HAVE_RANDOM_UUID -#define HAVE_RANDOM_UUID (HAVE_SYS_SYSCTL_H && defined __linux) /* RANDOM_UUID is an enum, not macro */ -#endif - -#ifndef HAVE_KERN_URND -#define HAVE_KERN_URND (defined KERN_URND) -#endif - -#ifndef HAVE_KERN_ARND -#define HAVE_KERN_ARND (defined KERN_ARND) -#endif static int randL_stir(struct randL_state *st, unsigned rqstd) { unsigned count = 0; int error; unsigned char data[256]; -#if HAVE_RANDOM_UUID || HAVE_KERN_URND || HAVE_KERN_ARND -#if HAVE_RANDOM_UUID - int mib[] = { CTL_KERN, KERN_RANDOM, RANDOM_UUID }; -#elif HAVE_KERN_URND - int mib[] = { CTL_KERN, KERN_URND }; -#else - int mib[] = { CTL_KERN, KERN_ARND }; -#endif - - while (count < rqstd) { +#if HAVE_ARC4RANDOM + while (count < rqst) { size_t n = MIN(rqstd - count, sizeof data); - if (0 != sysctl(mib, countof(mib), data, &n, (void *)0, 0)) - break; + arc4random(data, n); RAND_add(data, n, n); @@ -7856,6 +7841,22 @@ static int randL_stir(struct randL_state *st, unsigned rqstd) { } #endif +#if HAVE_GETRANDOM + while (count < rqst) { + size_t n = MIN(rqstd - count, sizeof data); + + n = getrandom(data, n, 0); + + if (n == -1) { + break; + } + + RAND_add(data, n, n); + + count += n; + } +#endif + if (count < rqstd) { #if defined O_CLOEXEC && (!defined _AIX /* O_CLOEXEC overflows int */) int fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC); -- cgit v1.2.3-59-g8ed1b From 7d6202bfa85e8f0bf90590a9381757f15e296a33 Mon Sep 17 00:00:00 2001 From: Ondřej Surý Date: Tue, 30 Aug 2016 10:25:36 +0200 Subject: Reinstate sysctl call for older Linux kernels --- src/openssl.c | 37 +++++++++++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 8 deletions(-) (limited to 'src/openssl.c') diff --git a/src/openssl.c b/src/openssl.c index 6addcaa..7c28c84 100644 --- a/src/openssl.c +++ b/src/openssl.c @@ -60,6 +60,8 @@ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0) #define HAVE_GETRANDOM #include +#else +#define HAVE_SYS_SYSCTL_H #endif #endif @@ -7824,13 +7826,20 @@ static struct randL_state *randL_getstate(lua_State *L) { return lua_touserdata(L, lua_upvalueindex(1)); } /* randL_getstate() */ +#if HAVE_SYS_SYSCTL_H +#include /* CTL_KERN KERN_RANDOM RANDOM_UUID KERN_URND KERN_ARND sysctl(2) */ +#endif + +#ifndef HAVE_RANDOM_UUID +#define HAVE_RANDOM_UUID (HAVE_SYS_SYSCTL_H && defined __linux__) /* RANDOM_UUID is an enum, not macro */ +#endif static int randL_stir(struct randL_state *st, unsigned rqstd) { unsigned count = 0; int error; unsigned char data[256]; -#if HAVE_ARC4RANDOM - while (count < rqst) { +#if defined(HAVE_ARC4RANDOM) + while (count < rqstd) { size_t n = MIN(rqstd - count, sizeof data); arc4random(data, n); @@ -7839,22 +7848,34 @@ static int randL_stir(struct randL_state *st, unsigned rqstd) { count += n; } -#endif - -#if HAVE_GETRANDOM - while (count < rqst) { +#elif defined(HAVE_GETRANDOM) + while (count < rqstd) { size_t n = MIN(rqstd - count, sizeof data); n = getrandom(data, n, 0); if (n == -1) { - break; + break; } - RAND_add(data, n, n); + RAND_add(data, n, n); + + count += n; + } +#elif HAVE_RANDOM_UUID + int mib[] = { CTL_KERN, KERN_RANDOM, RANDOM_UUID }; + + while (count < rqstd) { + size_t n = MIN(rqstd - count, sizeof data); + + if (0 != sysctl(mib, countof(mib), data, &n, (void *)0, 0)) + break; + + RAND_add(data, n, n); count += n; } + #endif if (count < rqstd) { -- cgit v1.2.3-59-g8ed1b From 45dfa8916f911e55b60cb03c1cd0f6cea1141b63 Mon Sep 17 00:00:00 2001 From: Ondřej Surý Date: Tue, 30 Aug 2016 10:29:57 +0200 Subject: Use RAND_seed() instead of RAND_add() where appropriate --- src/openssl.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/openssl.c') diff --git a/src/openssl.c b/src/openssl.c index 7c28c84..9fc4595 100644 --- a/src/openssl.c +++ b/src/openssl.c @@ -7844,7 +7844,7 @@ static int randL_stir(struct randL_state *st, unsigned rqstd) { arc4random(data, n); - RAND_add(data, n, n); + RAND_seed(data, n); count += n; } @@ -7858,7 +7858,7 @@ static int randL_stir(struct randL_state *st, unsigned rqstd) { break; } - RAND_add(data, n, n); + RAND_seed(data, n); count += n; } @@ -7871,7 +7871,7 @@ static int randL_stir(struct randL_state *st, unsigned rqstd) { if (0 != sysctl(mib, countof(mib), data, &n, (void *)0, 0)) break; - RAND_add(data, n, n); + RAND_seed(data, n); count += n; } @@ -7906,7 +7906,7 @@ static int randL_stir(struct randL_state *st, unsigned rqstd) { goto error; default: - RAND_add(data, n, n); + RAND_seed(data, n); count += n; } -- cgit v1.2.3-59-g8ed1b From 6a6a85b0ecfbe1a68e0b2d86ba1f75a17f8c1598 Mon Sep 17 00:00:00 2001 From: Ondřej Surý Date: Tue, 30 Aug 2016 10:41:12 +0200 Subject: Add __DragonFly__ and generic BSD detection for ARC4RANDOM --- src/openssl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/openssl.c') diff --git a/src/openssl.c b/src/openssl.c index 9fc4595..136110f 100644 --- a/src/openssl.c +++ b/src/openssl.c @@ -51,7 +51,7 @@ #define HAVE_ARC4RANDOM #endif -#if defined(__FreeBSD_kernel__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) +#if defined(__FreeBSD_kernel__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(BSD) #define HAVE_ARC4RANDOM #endif -- cgit v1.2.3-59-g8ed1b From 705053409dade9bc9f691a25f9754a129fa37406 Mon Sep 17 00:00:00 2001 From: Ondřej Surý Date: Tue, 30 Aug 2016 11:18:13 +0200 Subject: Use syscall() to call getrandom() --- src/openssl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/openssl.c') diff --git a/src/openssl.c b/src/openssl.c index 136110f..c25651b 100644 --- a/src/openssl.c +++ b/src/openssl.c @@ -59,6 +59,7 @@ #include #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0) #define HAVE_GETRANDOM +#include #include #else #define HAVE_SYS_SYSCTL_H @@ -7852,7 +7853,7 @@ static int randL_stir(struct randL_state *st, unsigned rqstd) { while (count < rqstd) { size_t n = MIN(rqstd - count, sizeof data); - n = getrandom(data, n, 0); + n = syscall(SYS_getrandom, data, n, 0); if (n == -1) { break; -- cgit v1.2.3-59-g8ed1b From 5949f01087291c0a6431f90264fc9795b133867f Mon Sep 17 00:00:00 2001 From: William Ahern Date: Wed, 19 Oct 2016 13:15:48 -0700 Subject: there are no kernel headers installed by default in Alpine Linux (Linux/musl) so use alternate feature test; support running binaries built with getrandom on older kernels with only sysctl(RANDOM_UUID); change preprocessor test for feature macros so they can be easily overridden with build flags; and remove feature macro definitions in favor of those in config.h (config.h.guess) --- src/openssl.c | 56 +++++++++++++++++++++++++------------------------------- 1 file changed, 25 insertions(+), 31 deletions(-) (limited to 'src/openssl.c') diff --git a/src/openssl.c b/src/openssl.c index c25651b..78dbd65 100644 --- a/src/openssl.c +++ b/src/openssl.c @@ -23,6 +23,10 @@ * USE OR OTHER DEALINGS IN THE SOFTWARE. * ========================================================================== */ +#if HAVE_CONFIG_H +#include "config.h" +#endif + #include /* INT_MAX INT_MIN LLONG_MAX LLONG_MIN UCHAR_MAX ULLONG_MAX */ #include /* uintptr_t */ #include /* memset(3) strerror_r(3) */ @@ -48,22 +52,6 @@ #if __APPLE__ #include /* mach_absolute_time() */ -#define HAVE_ARC4RANDOM -#endif - -#if defined(__FreeBSD_kernel__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(BSD) -#define HAVE_ARC4RANDOM -#endif - -#if defined(__linux__) -#include -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0) -#define HAVE_GETRANDOM -#include -#include -#else -#define HAVE_SYS_SYSCTL_H -#endif #endif #include @@ -95,10 +83,6 @@ #define LIBRESSL_PREREQ(M, m, p) \ (LIBRESSL_VERSION_NUMBER >= (((M) << 28) | ((m) << 20) | ((p) << 12))) -#ifndef HAVE_DLADDR -#define HAVE_DLADDR (!defined _AIX) /* TODO: https://root.cern.ch/drupal/content/aix-and-dladdr */ -#endif - #ifndef HAVE_SSL_CTX_SET_ALPN_PROTOS #define HAVE_SSL_CTX_SET_ALPN_PROTOS OPENSSL_PREREQ(1, 0, 2) #endif @@ -7827,19 +7811,20 @@ static struct randL_state *randL_getstate(lua_State *L) { return lua_touserdata(L, lua_upvalueindex(1)); } /* randL_getstate() */ -#if HAVE_SYS_SYSCTL_H -#include /* CTL_KERN KERN_RANDOM RANDOM_UUID KERN_URND KERN_ARND sysctl(2) */ +#if HAVE_SYS_SYSCALL_H +#include /* SYS_getrandom syscall(2) */ #endif -#ifndef HAVE_RANDOM_UUID -#define HAVE_RANDOM_UUID (HAVE_SYS_SYSCTL_H && defined __linux__) /* RANDOM_UUID is an enum, not macro */ +#if HAVE_SYS_SYSCTL_H +#include /* CTL_KERN KERN_RANDOM RANDOM_UUID sysctl(2) */ #endif static int randL_stir(struct randL_state *st, unsigned rqstd) { unsigned count = 0; int error; unsigned char data[256]; -#if defined(HAVE_ARC4RANDOM) + +#if HAVE_ARC4RANDOM while (count < rqstd) { size_t n = MIN(rqstd - count, sizeof data); @@ -7849,11 +7834,14 @@ static int randL_stir(struct randL_state *st, unsigned rqstd) { count += n; } -#elif defined(HAVE_GETRANDOM) +#endif + +#if HAVE_SYSCALL && HAVE_DECL_SYS_GETRANDOM while (count < rqstd) { - size_t n = MIN(rqstd - count, sizeof data); + size_t lim = MIN(rqstd - count, sizeof data); + int n; - n = syscall(SYS_getrandom, data, n, 0); + n = syscall(SYS_getrandom, data, lim, 0); if (n == -1) { break; @@ -7863,10 +7851,11 @@ static int randL_stir(struct randL_state *st, unsigned rqstd) { count += n; } -#elif HAVE_RANDOM_UUID - int mib[] = { CTL_KERN, KERN_RANDOM, RANDOM_UUID }; +#endif +#if HAVE_SYS_SYSCTL_H && HAVE_DECL_RANDOM_UUID while (count < rqstd) { + int mib[] = { CTL_KERN, KERN_RANDOM, RANDOM_UUID }; size_t n = MIN(rqstd - count, sizeof data); if (0 != sysctl(mib, countof(mib), data, &n, (void *)0, 0)) @@ -7945,7 +7934,12 @@ error:; #elif defined __sun /* * NOTE: Linux requires -lrt for clock_gettime, and in any event - * already has RANDOM_UUID. The BSDs have KERN_URND and KERN_ARND. + * should have RANDOM_UUID or getrandom. (Though, some middle-aged + * kernels might have neither). The BSDs have arc4random which + * should be using KERN_URND, KERN_ARND, and more recently + * getentropy. (Though, again, some older BSD kernels used an + * arc4random implementation that opened /dev/urandom.) + * * Just do this for Solaris to keep things simple. We've already * crossed the line of what can be reasonably accomplished on * unreasonable platforms. -- cgit v1.2.3-59-g8ed1b