From 9f5312cc4ec704d4a58df52b00987109ac327af0 Mon Sep 17 00:00:00 2001 From: nia Date: Thu, 11 Jun 2020 13:32:13 +0100 Subject: [PATCH] entropy: Add support for BSD sysctl(KERN_ARND) This is basically the same as reading from /dev/urandom on supported systems, only it has a limit of 256 bytes per call, and does not require an open file descriptor (so it can be used in chroots, when resource limits are in place, or are otherwise exhausted). It's functionally equivalent to the comparable function getentropy(), but has been around for longer. It's actually used to implement getentropy in FreeBSD's libc. Discussions about adding getrandom or getentropy to NetBSD are still ongoing. It's present in all supported versions of FreeBSD and NetBSD. It's not present in DragonFly or OpenBSD. Documentation: https://netbsd.gw.com/cgi-bin/man-cgi?sysctl+7 Comparable code in OpenSSL: https://github.com/openssl/openssl/blob/ddec332f329a432a45c0131d83f3bfb46114532b/crypto/rand/rand_unix.c#L208 Signed-off-by: nia --- library/entropy_poll.c | 45 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/library/entropy_poll.c b/library/entropy_poll.c index 8b4a5af9e8..203034eb49 100644 --- a/library/entropy_poll.c +++ b/library/entropy_poll.c @@ -115,6 +115,41 @@ static int getrandom_wrapper( void *buf, size_t buflen, unsigned int flags ) #endif /* SYS_getrandom */ #endif /* __linux__ || __midipix__ */ +/* + * Some BSD systems provide KERN_ARND. + * This is equivalent to reading from /dev/urandom, only it doesn't require an + * open file descriptor, and provides up to 256 bytes per call (basically the + * same as getentropy(), but with a longer history). + * + * Documentation: https://netbsd.gw.com/cgi-bin/man-cgi?sysctl+7 + */ +#if (defined(__FreeBSD__) || defined(__NetBSD__)) && !defined(HAVE_GETRANDOM) +#include +#include +#if defined(KERN_ARND) +#define HAVE_SYSCTL_ARND + +static int sysctl_wrapper ( void *buf, size_t buflen ) +{ + int name[2]; + size_t len; + + name[0] = CTL_KERN; + name[1] = KERN_ARND; + + while( buflen > 0 ) + { + len = buflen > 256 ? 256 : buflen; + if( sysctl(name, 2, buf, &len, NULL, 0) == -1 ) + return( -1 ); + buflen -= len; + buf += len; + } + return( 0 ); +} +#endif /* KERN_ARND */ +#endif /* __FreeBSD__ || __NetBSD__ */ + #include int mbedtls_platform_entropy_poll( void *data, @@ -139,6 +174,15 @@ int mbedtls_platform_entropy_poll( void *data, ((void) ret); #endif /* HAVE_GETRANDOM */ +#if defined(HAVE_SYSCTL_ARND) + ((void) file); + ((void) read_len); + if( sysctl_wrapper( output, len ) == -1 ) + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + *olen = len; + return( 0 ); +#else + *olen = 0; file = fopen( "/dev/urandom", "rb" ); @@ -156,6 +200,7 @@ int mbedtls_platform_entropy_poll( void *data, *olen = len; return( 0 ); +#endif /* HAVE_SYSCTL_ARND */ } #endif /* _WIN32 && !EFIX64 && !EFI32 */ #endif /* !MBEDTLS_NO_PLATFORM_ENTROPY */