use getrandom() on recent linux distros
Instead of using the internal DRBG-based RNG, use the `getrandom()` system call where available. Keep the existing version as fall-back for other systems that don't provide that system call. ... and for cases where auto-detection fails or the user simply wants to use the internal RNG a new configure-switch is provided. Signed-off-by: Steffen Jaeckel <jaeckel-floss@eyet-services.de>
This commit is contained in:
@@ -41,6 +41,8 @@ AC_ARG_ENABLE([tls],
|
||||
[AS_HELP_STRING([--disable-tls], [disable TLS support])])
|
||||
AC_ARG_ENABLE([cares],
|
||||
[AS_HELP_STRING([--enable-cares], [use c-ares for DNS resolution])])
|
||||
AC_ARG_ENABLE([getrandom],
|
||||
[AS_HELP_STRING([--disable-getrandom], [disable usage of the getrandom() system call])])
|
||||
|
||||
AC_ARG_ENABLE([fuzzing],
|
||||
[AS_HELP_STRING([--enable-fuzzing], [turn on fuzzing test])],
|
||||
@@ -96,6 +98,12 @@ elif test "x$enable_tls" != xno; then
|
||||
)])
|
||||
fi
|
||||
|
||||
AC_CHECK_FUNCS([getrandom], [], [enable_getrandom=no])
|
||||
if test "$enable_getrandom" = "no"; then
|
||||
AC_DEFINE(DONT_USE_GETRANDOM)
|
||||
AC_MSG_NOTICE([libstrophe will not use the getrandom() system call])
|
||||
fi
|
||||
|
||||
with_parser=""
|
||||
if test "x$with_libxml2" != xyes; then
|
||||
PKG_CHECK_MODULES([expat], [expat >= 2.0.0],
|
||||
|
||||
59
src/rand.c
59
src/rand.c
@@ -23,13 +23,23 @@
|
||||
#include <string.h> /* memeset */
|
||||
#include <time.h> /* clock, time */
|
||||
|
||||
#if !defined(DONT_USE_GETRANDOM) && defined(__linux__) && \
|
||||
defined(__GLIBC_PREREQ)
|
||||
#if __GLIBC_PREREQ(2, 25)
|
||||
#define USE_GETRANDOM
|
||||
#include <sys/random.h>
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "common.h" /* xmpp_alloc, xmpp_free */
|
||||
#include "ostypes.h" /* uint8_t, uint32_t, size_t */
|
||||
#include "sha1.h"
|
||||
#include "snprintf.h" /* xmpp_snprintf */
|
||||
|
||||
#include "rand.h" /* xmpp_rand_t */
|
||||
|
||||
#ifndef USE_GETRANDOM
|
||||
#include "sha1.h"
|
||||
|
||||
#define outlen SHA1_DIGEST_SIZE
|
||||
#define seedlen (440 / 8)
|
||||
#define reseed_interval 0x7fffffff
|
||||
@@ -285,6 +295,51 @@ void xmpp_rand_bytes(xmpp_rand_t *rand, unsigned char *output, size_t len)
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static int _read_getrandom(void *p, size_t n)
|
||||
{
|
||||
unsigned char *q = (unsigned char *)p;
|
||||
while (n > 0u) {
|
||||
ssize_t ret = getrandom(q, n, 0);
|
||||
if (ret < 0) {
|
||||
if (errno == EINTR) {
|
||||
continue;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
q += ret;
|
||||
n -= (size_t)ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct _xmpp_rand_t {
|
||||
char nothing;
|
||||
};
|
||||
|
||||
static xmpp_rand_t _xmpp_rand;
|
||||
|
||||
xmpp_rand_t *xmpp_rand_new(xmpp_ctx_t *ctx)
|
||||
{
|
||||
UNUSED(ctx);
|
||||
return &_xmpp_rand;
|
||||
}
|
||||
|
||||
void xmpp_rand_free(xmpp_ctx_t *ctx, xmpp_rand_t *rand)
|
||||
{
|
||||
UNUSED(ctx);
|
||||
assert(rand == &_xmpp_rand);
|
||||
}
|
||||
|
||||
void xmpp_rand_bytes(xmpp_rand_t *rand, unsigned char *output, size_t len)
|
||||
{
|
||||
assert(rand == &_xmpp_rand);
|
||||
assert(_read_getrandom(output, len) == 0);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int xmpp_rand(xmpp_rand_t *rand)
|
||||
{
|
||||
int result;
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
/* include rand.c to access private structures and functions */
|
||||
#include "rand.c"
|
||||
|
||||
#ifndef USE_GETRANDOM
|
||||
|
||||
/* stubs to build test without whole libstrophe */
|
||||
void *xmpp_alloc(const xmpp_ctx_t *ctx, size_t size)
|
||||
{
|
||||
@@ -160,3 +162,19 @@ int main()
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int main()
|
||||
{
|
||||
uint8_t output[1024];
|
||||
xmpp_rand_t *rand = xmpp_rand_new(NULL);
|
||||
|
||||
assert(rand != NULL);
|
||||
/* this would assert if it failed */
|
||||
xmpp_rand_bytes(rand, output, sizeof(output));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user