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])])
|
[AS_HELP_STRING([--disable-tls], [disable TLS support])])
|
||||||
AC_ARG_ENABLE([cares],
|
AC_ARG_ENABLE([cares],
|
||||||
[AS_HELP_STRING([--enable-cares], [use c-ares for DNS resolution])])
|
[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],
|
AC_ARG_ENABLE([fuzzing],
|
||||||
[AS_HELP_STRING([--enable-fuzzing], [turn on fuzzing test])],
|
[AS_HELP_STRING([--enable-fuzzing], [turn on fuzzing test])],
|
||||||
@@ -96,6 +98,12 @@ elif test "x$enable_tls" != xno; then
|
|||||||
)])
|
)])
|
||||||
fi
|
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=""
|
with_parser=""
|
||||||
if test "x$with_libxml2" != xyes; then
|
if test "x$with_libxml2" != xyes; then
|
||||||
PKG_CHECK_MODULES([expat], [expat >= 2.0.0],
|
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 <string.h> /* memeset */
|
||||||
#include <time.h> /* clock, time */
|
#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 "common.h" /* xmpp_alloc, xmpp_free */
|
||||||
#include "ostypes.h" /* uint8_t, uint32_t, size_t */
|
#include "ostypes.h" /* uint8_t, uint32_t, size_t */
|
||||||
#include "sha1.h"
|
|
||||||
#include "snprintf.h" /* xmpp_snprintf */
|
|
||||||
|
|
||||||
#include "rand.h" /* xmpp_rand_t */
|
#include "rand.h" /* xmpp_rand_t */
|
||||||
|
|
||||||
|
#ifndef USE_GETRANDOM
|
||||||
|
#include "sha1.h"
|
||||||
|
|
||||||
#define outlen SHA1_DIGEST_SIZE
|
#define outlen SHA1_DIGEST_SIZE
|
||||||
#define seedlen (440 / 8)
|
#define seedlen (440 / 8)
|
||||||
#define reseed_interval 0x7fffffff
|
#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 xmpp_rand(xmpp_rand_t *rand)
|
||||||
{
|
{
|
||||||
int result;
|
int result;
|
||||||
|
|||||||
@@ -20,6 +20,8 @@
|
|||||||
/* include rand.c to access private structures and functions */
|
/* include rand.c to access private structures and functions */
|
||||||
#include "rand.c"
|
#include "rand.c"
|
||||||
|
|
||||||
|
#ifndef USE_GETRANDOM
|
||||||
|
|
||||||
/* stubs to build test without whole libstrophe */
|
/* stubs to build test without whole libstrophe */
|
||||||
void *xmpp_alloc(const xmpp_ctx_t *ctx, size_t size)
|
void *xmpp_alloc(const xmpp_ctx_t *ctx, size_t size)
|
||||||
{
|
{
|
||||||
@@ -160,3 +162,19 @@ int main()
|
|||||||
|
|
||||||
return 0;
|
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