Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/configs/os-check-linux.json
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,12 @@
{"name": "no-verify-oid-fpki", "minutes": 1.2,
"configure": ["CPPFLAGS=-DNO_VERIFY_OID -DWOLFSSL_FPKI"]},
{"name": "no-verify-oid", "minutes": 1.1, "configure": ["CPPFLAGS=-DNO_VERIFY_OID"]},
{"name": "rng-seed-device", "minutes": 1.1,
"comment": "Seed the RNG from a nominated device. /dev/urandom stands in for a hardware RNG so the WC_RNG_SEED_DEVICE read path is actually exercised on a runner.",
"configure": ["--with-rng-seed-device=/dev/urandom"]},
{"name": "rng-seed-device-fallback", "minutes": 1.1,
"comment": "Nominated seed device that cannot be opened, so every test runs through the fallback to the default seed sources.",
"configure": ["--with-rng-seed-device=/nonexistent/hwrng"]},
{"name": "no-server-no-client-auth", "minutes": 1.0,
"configure": ["CPPFLAGS=-DNO_WOLFSSL_SERVER -DWOLFSSL_NO_CLIENT_AUTH"]},
{"name": "no-wolfssl-client", "minutes": 1.0,
Expand Down
8 changes: 8 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3768,6 +3768,14 @@ if(WOLFSSL_ECC AND WOLFSSL_ECC_MIN_KEY_SZ)
list(APPEND WOLFSSL_DEFINITIONS "-DECC_MIN_KEY_SZ=${WOLFSSL_ECC_MIN_KEY_SZ}")
endif()

# RNG seed device (best effort, falls back to the default sources)
set(WOLFSSL_RNG_SEED_DEVICE "" CACHE STRING
"Seed the RNG from this device before the default sources, e.g. /dev/hwrng (default: disabled)")
if(WOLFSSL_RNG_SEED_DEVICE)
list(APPEND WOLFSSL_DEFINITIONS
"-DWC_RNG_SEED_DEVICE=\"${WOLFSSL_RNG_SEED_DEVICE}\"")
endif()


####################################################
# Additional crypto/TLS feature options (parity with configure.ac)
Expand Down
2 changes: 2 additions & 0 deletions cmake/options.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -611,6 +611,8 @@ extern "C" {
#cmakedefine MAX_EX_DATA @MAX_EX_DATA@
#undef ECC_MIN_KEY_SZ
#cmakedefine ECC_MIN_KEY_SZ @ECC_MIN_KEY_SZ@
#undef WC_RNG_SEED_DEVICE
#cmakedefine WC_RNG_SEED_DEVICE @WC_RNG_SEED_DEVICE@

/* parity: crypto/TLS feature options (wave B) */
#undef WOLFSSL_MD2
Expand Down
17 changes: 17 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -8749,6 +8749,23 @@ then
fi


# RNG seed device (best effort, falls back to the default sources)
AC_ARG_WITH([rng-seed-device],
[AS_HELP_STRING([--with-rng-seed-device=PATH],[Seed the RNG from PATH before the default sources, e.g. /dev/hwrng (default: disabled)])],
[ RNG_SEED_DEVICE=$withval ],
[ RNG_SEED_DEVICE=no ]
)

if test "$RNG_SEED_DEVICE" != "no"
then
if test "$RNG_SEED_DEVICE" = "yes"
then
RNG_SEED_DEVICE="/dev/hwrng"
fi
AM_CFLAGS="$AM_CFLAGS -DWC_RNG_SEED_DEVICE=\\\"$RNG_SEED_DEVICE\\\""
fi
Comment on lines +8764 to +8766


# Filesystem Build
if test "$HAVE_KERNEL_MODE" = "yes"
then
Expand Down
92 changes: 75 additions & 17 deletions wolfcrypt/src/random.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ This library contains implementation for the random number generator.
* FORCE_FAILURE_GETRANDOM: Force getrandom failure (testing) default: off
* NO_DEV_RANDOM: Don't use /dev/random for seeding default: off
* NO_DEV_URANDOM: Don't use /dev/urandom for seeding default: off
* WC_RNG_SEED_DEVICE: Device tried before the usual seed default: off
* sources. Must be a quoted string,
* e.g. -DWC_RNG_SEED_DEVICE='"/dev/hwrng"'
* HAVE_INTEL_RDRAND: Use Intel RDRAND instruction default: off
* HAVE_INTEL_RDSEED: Use Intel RDSEED instruction default: off
* HAVE_AMD_RDSEED: Use AMD RDSEED instruction default: off
Expand Down Expand Up @@ -352,6 +355,11 @@ enum {
#error RNG_MAX_BLOCK_LEN is larger than NIST DBRG max request length
#endif

/* the seed device is read through the filesystem API */
#if defined(WC_RNG_SEED_DEVICE) && defined(NO_FILESYSTEM)
#error WC_RNG_SEED_DEVICE requires filesystem support
#endif

enum {
drbgInitC = 0,
drbgReseed = 1,
Expand Down Expand Up @@ -5933,6 +5941,12 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
{
int ret = 0;
#ifdef WC_RNG_SEED_DEVICE
byte* devOut;
word32 devSz;
int devFd;
int devLen;
#endif

/* Validate output before any entropy backend dereferences it: some
* (e.g. glibc's vDSO getrandom()) fault on a NULL buffer rather than
Expand Down Expand Up @@ -5971,6 +5985,43 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)

#if !defined(HAVE_ENTROPY_MEMUSE) || !defined(ENTROPY_MEMUSE_FORCE_FAILURE)

#ifdef WC_RNG_SEED_DEVICE
/* Nominated entropy source, usually a hardware RNG. Best effort: on
* any failure fall through to the default sources below. Those refill
* the whole request from the start, so bytes a partial read left in
* output are overwritten rather than mixed in. */
devOut = output;
devSz = sz;
devFd = wc_open_cloexec(WC_RNG_SEED_DEVICE, O_RDONLY);
if (devFd != XBADFD) {
while (devSz > 0) {
errno = 0;
devLen = (int)read(devFd, devOut, devSz);
if (devLen < 0) {
if (errno == EINTR)
continue; /* interrupted, read again */
break;
}
if (devLen == 0)
break; /* at EOF, will never fill the request */

devSz -= (word32)devLen;
devOut += devLen;
}
close(devFd);
}
#if defined(DEBUG_WOLFSSL)
if (devSz == 0)
WOLFSSL_MSG("seeded from WC_RNG_SEED_DEVICE.");
else
WOLFSSL_MSG("WC_RNG_SEED_DEVICE unusable, using default.");
#endif /* DEBUG_WOLFSSL */
if (devSz == 0) {
/* success, we're done */
return 0;
}
#endif /* WC_RNG_SEED_DEVICE */

#if defined(HAVE_INTEL_RDSEED) || defined(HAVE_AMD_RDSEED)
if (IS_INTEL_RDSEED(intel_flags)) {
ret = wc_GenerateSeed_IntelRD(NULL, output, sz);
Expand Down Expand Up @@ -6038,44 +6089,50 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
#ifdef WOLFSSL_KEEP_RNG_SEED_FD_OPEN
if (!os->seedFdOpen)
{
os->fd = XBADFD;
#ifndef NO_DEV_URANDOM /* way to disable use of /dev/urandom */
os->fd = wc_open_cloexec("/dev/urandom", O_RDONLY);
if (os->fd == XBADFD) {
os->fd = wc_open_cloexec("/dev/urandom", O_RDONLY);
#if defined(DEBUG_WOLFSSL)
WOLFSSL_MSG("opened /dev/urandom.");
if (os->fd != XBADFD)
WOLFSSL_MSG("opened /dev/urandom.");
#endif /* DEBUG_WOLFSSL */
if (os->fd == XBADFD)
}
#endif /* NO_DEV_URANDOM */
{
if (os->fd == XBADFD) {
/* may still have /dev/random */
os->fd = wc_open_cloexec("/dev/random", O_RDONLY);
#if defined(DEBUG_WOLFSSL)
WOLFSSL_MSG("opened /dev/random.");
if (os->fd != XBADFD)
WOLFSSL_MSG("opened /dev/random.");
#endif /* DEBUG_WOLFSSL */
if (os->fd == XBADFD)
return OPEN_RAN_E;
else {
os->keepSeedFdOpen = 0;
os->seedFdOpen = 1;
}
os->keepSeedFdOpen = 0;
os->seedFdOpen = 1;
}
else {
os->keepSeedFdOpen = 1;
os->seedFdOpen = 1;
}
}
#else /* WOLFSSL_KEEP_RNG_SEED_FD_OPEN */
#ifndef NO_DEV_URANDOM /* way to disable use of /dev/urandom */
os->fd = wc_open_cloexec("/dev/urandom", O_RDONLY);
os->fd = XBADFD;
#ifndef NO_DEV_URANDOM /* way to disable use of /dev/urandom */
if (os->fd == XBADFD) {
os->fd = wc_open_cloexec("/dev/urandom", O_RDONLY);
#if defined(DEBUG_WOLFSSL)
WOLFSSL_MSG("opened /dev/urandom.");
if (os->fd != XBADFD)
WOLFSSL_MSG("opened /dev/urandom.");
#endif /* DEBUG_WOLFSSL */
if (os->fd == XBADFD)
#endif /* !NO_DEV_URANDOM */
{
}
#endif /* !NO_DEV_URANDOM */
if (os->fd == XBADFD) {
/* may still have /dev/random */
os->fd = wc_open_cloexec("/dev/random", O_RDONLY);
#if defined(DEBUG_WOLFSSL)
WOLFSSL_MSG("opened /dev/random.");
if (os->fd != XBADFD)
WOLFSSL_MSG("opened /dev/random.");
#endif /* DEBUG_WOLFSSL */
if (os->fd == XBADFD)
return OPEN_RAN_E;
Expand All @@ -6086,7 +6143,8 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
#endif /* DEBUG_WOLFSSL */
while (sz) {
int len = (int)read(os->fd, output, sz);
if (len == -1) {
/* EOF never fills the request, don't retry forever */
if (len <= 0) {
ret = READ_RAN_E;
break;
}
Expand Down
Loading