Skip to content

Commit

Permalink
Add support for gettng entropy using system calls
Browse files Browse the repository at this point in the history
  • Loading branch information
kroeckx committed Apr 14, 2018
1 parent d47eb76 commit bcdae92
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 11 deletions.
3 changes: 2 additions & 1 deletion INSTALL
Expand Up @@ -224,7 +224,8 @@
os: Use a trusted operating system entropy source.
This is the default method if such an entropy
source exists.
getrandom: Use the L<getrandom(2)> system call if available.
getrandom: Use the L<getrandom(2)> or equivalant system
call.
devrandom: Use the the first device from the DEVRANDOM list
which can be opened to read random bytes. The
DEVRANDOM preprocessor constant expands to
Expand Down
102 changes: 92 additions & 10 deletions crypto/rand/rand_unix.c
Expand Up @@ -7,13 +7,25 @@
* https://www.openssl.org/source/license.html
*/

#define _GNU_SOURCE
#include "e_os.h"
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/rand.h>
#include "rand_lcl.h"
#include "internal/rand_int.h"
#include <stdio.h>
#if defined(__linux)
# include <sys/syscall.h>
#endif
#if defined(__FreeBSD__)
# include <sys/types.h>
# include <sys/sysctl.h>
# include <sys/param.h>
#endif
#if defined(__OpenBSD__)
# include <sys/param.h>
#endif
#ifdef OPENSSL_SYS_UNIX
# include <sys/types.h>
# include <unistd.h>
Expand Down Expand Up @@ -59,6 +71,8 @@ static uint64_t get_timer_bits(void);
# endif
#endif

int syscall_random(void *buf, size_t buflen);

#if (defined(OPENSSL_SYS_VXWORKS) || defined(OPENSSL_SYS_UEFI)) && \
!defined(OPENSSL_RAND_SEED_NONE)
# error "UEFI and VXWorks only support seeding NONE"
Expand Down Expand Up @@ -149,26 +163,94 @@ size_t rand_pool_acquire_entropy(RAND_POOL *pool)
# error "Seeding uses urandom but DEVRANDOM is not configured"
# endif

# if defined(__GLIBC__) && defined(__GLIBC_PREREQ)
# if __GLIBC_PREREQ(2, 25)
# define OPENSSL_HAVE_GETRANDOM
# endif
# endif

# if (defined(__FreeBSD__) && __FreeBSD_version >= 1200061)
# define OPENSSL_HAVE_GETRANDOM
# endif

# if defined(OPENSSL_HAVE_GETRANDOM)
# include <sys/random.h>
# endif

# if defined(OPENSSL_RAND_SEED_OS)
# if !defined(DEVRANDOM)
# error "OS seeding requires DEVRANDOM to be configured"
# endif
# define OPENSSL_RAND_SEED_GETRANDOM
# define OPENSSL_RAND_SEED_DEVRANDOM
# if defined(__GLIBC__) && defined(__GLIBC_PREREQ)
# if __GLIBC_PREREQ(2, 25)
# define OPENSSL_RAND_SEED_GETRANDOM
# endif
# endif
# endif

# ifdef OPENSSL_RAND_SEED_GETRANDOM
# include <sys/random.h>
# endif

# if defined(OPENSSL_RAND_SEED_LIBRANDOM)
# error "librandom not (yet) supported"
# endif

# if defined(__FreeBSD__) && defined(KERN_ARND)
/*
* sysctl_random(): Use sysctl() to read a random number from the kernel
* Returns the size on success, 0 on failure.
*/
static size_t sysctl_random(char *buf, size_t buflen)
{
int mib[2];
size_t done = 0;
size_t len;

/*
* Old implementations returned longs, newer versions support variable
* sizes up to 256 byte. The code below would not work properly when
* the sysctl returns long and we want to request something not a multiple
* of longs.
*/
if (buflen % sizeof(long) != 0)
return 0;

mib[0] = CTL_KERN;
mib[1] = KERN_ARND;

do {
len = buflen;
if (sysctl(mib, 2, buf, &len, NULL, 0) == -1)
return done;
done += len;
buf += len;
buflen -= len;
} while (buflen > 0);

return done;
}
# endif

/*
* syscall_random(): Try to get random data using a system call
* returns the number of bytes returned in buf, or <= 0 on error.
*/
int syscall_random(void *buf, size_t buflen)
{
# if defined(OPENSSL_HAVE_GETRANDOM)
return (int)getrandom(buf, buflen, 0);
# endif

# if defined(__linux) && defined(SYS_getrandom)
return (int)syscall(SYS_getrandom, buf, buflen, 0);
# endif

# if defined(__FreeBSD__) && defined(KERN_ARND)
return (int)sysctl_random(buf, buflen);
# endif

/* Supported since OpenBSD 5.6 */
# if defined(__OpenBSD__) && OpenBSD >= 201411
return getentropy(buf, buflen);
# endif

return -1;
}

/*
* Try the various seeding methods in turn, exit when successful.
*
Expand Down Expand Up @@ -201,7 +283,7 @@ size_t rand_pool_acquire_entropy(RAND_POOL *pool)
if (buffer != NULL) {
size_t bytes = 0;

if (getrandom(buffer, bytes_needed, 0) == (int)bytes_needed)
if (syscall_random(buffer, bytes_needed) == (int)bytes_needed)
bytes = bytes_needed;

rand_pool_add_end(pool, bytes, 8 * bytes);
Expand Down

0 comments on commit bcdae92

Please sign in to comment.