diff --git a/ChangeLog.d/sysctl-arnd-support.txt b/ChangeLog.d/sysctl-arnd-support.txt new file mode 100644 index 000000000..14ad67412 --- /dev/null +++ b/ChangeLog.d/sysctl-arnd-support.txt @@ -0,0 +1,2 @@ +Features + * Added support to entropy_poll for the kern.arandom syscall supported on some BSD systems. Contributed by Nia Alarie in #3423. diff --git a/library/entropy_poll.c b/library/entropy_poll.c index 8b4a5af9e..dc621836e 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_arnd_wrapper( unsigned char *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_arnd_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 */