diff --git a/ChangeLog b/ChangeLog index 9d1d7eb49..d33640911 100644 --- a/ChangeLog +++ b/ChangeLog @@ -31,6 +31,8 @@ Features * Support for 1/n-1 record splitting, a countermeasure against BEAST. * Certificate selection based on signature hash, prefering SHA-1 over SHA-2 for pre-1.2 clients when multiple certificates are available. + * Add support for getrandom() syscall on recent Linux kernels with Glibc or + a compatible enough libc (eg uClibc). Bugfix * Stack buffer overflow if ctr_drbg_update() is called with too large diff --git a/library/entropy_poll.c b/library/entropy_poll.c index 9ca9e9519..33e75bc65 100644 --- a/library/entropy_poll.c +++ b/library/entropy_poll.c @@ -73,6 +73,43 @@ int platform_entropy_poll( void *data, unsigned char *output, size_t len, } #else /* _WIN32 && !EFIX64 && !EFI32 */ +/* + * Test for Linux getrandom() support. + * Since there is no wrapper in the libc yet, use the generic syscall wrapper + * available in GNU libc and compatible libc's (eg uClibc). + */ +#if defined(__linux__) && defined(__GLIBC__) +#include <linux/version.h> +#include <unistd.h> +#include <sys/syscall.h> +#if defined(SYS_getrandom) +#define HAVE_GETRANDOM +static int getrandom_wrapper( void *buf, size_t buflen, unsigned int flags ) +{ + return( syscall( SYS_getrandom, buf, buflen, flags ) ); +} +#endif /* SYS_getrandom */ +#endif /* __linux__ */ + +#if defined(HAVE_GETRANDOM) + +#include <errno.h> + +int platform_entropy_poll( void *data, + unsigned char *output, size_t len, size_t *olen ) +{ + int ret; + ((void) data); + + if( ( ret = getrandom_wrapper( output, len, 0 ) ) < 0 ) + return( POLARSSL_ERR_ENTROPY_SOURCE_FAILED ); + + *olen = ret; + return( 0 ); +} + +#else /* HAVE_GETRANDOM */ + #include <stdio.h> int platform_entropy_poll( void *data, @@ -100,6 +137,7 @@ int platform_entropy_poll( void *data, return( 0 ); } +#endif /* HAVE_GETRANDOM */ #endif /* _WIN32 && !EFIX64 && !EFI32 */ #endif /* !POLARSSL_NO_PLATFORM_ENTROPY */