summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKai Engert <kaie@kuix.de>2018-04-20 16:33:08 +0200
committerKai Engert <kaie@kuix.de>2018-04-20 16:33:08 +0200
commit125b27bd98393a8376318cc41813231c11216a0a (patch)
tree0ab459b226cb9a54de9fb697d6fd715f2d4b6955
parent0b4df45ca6f49d13c6bc392a2be3a509c1d11f43 (diff)
downloadnss-hg-125b27bd98393a8376318cc41813231c11216a0a.tar.gz
Bug 1057343, Use Linux getrandom()/getentropy() kernel system call for obtaining entropy, r=fkiefer
-rw-r--r--coreconf/config.mk4
-rw-r--r--lib/freebl/unix_urandom.c33
2 files changed, 37 insertions, 0 deletions
diff --git a/coreconf/config.mk b/coreconf/config.mk
index 55d95c30e..b62f6cef4 100644
--- a/coreconf/config.mk
+++ b/coreconf/config.mk
@@ -181,6 +181,10 @@ ifndef NSS_FORCE_FIPS
DEFINES += -DNSS_NO_INIT_SUPPORT
endif
+ifdef NSS_SEED_ONLY_DEV_URANDOM
+DEFINES += -DSEED_ONLY_DEV_URANDOM
+endif
+
# Avoid building object leak test code for optimized library
ifndef BUILD_OPT
ifdef PKIX_OBJECT_LEAK_TEST
diff --git a/lib/freebl/unix_urandom.c b/lib/freebl/unix_urandom.c
index 25e6ad91c..4c65d8fe5 100644
--- a/lib/freebl/unix_urandom.c
+++ b/lib/freebl/unix_urandom.c
@@ -4,10 +4,14 @@
#include <fcntl.h>
#include <unistd.h>
+#include <errno.h>
#include "secerr.h"
#include "secrng.h"
#include "prprf.h"
+/* syscall getentropy() is limited to retrieving 256 bytes */
+#define GETENTROPY_MAX_BYTES 256
+
void
RNG_SystemInfoForRNG(void)
{
@@ -28,6 +32,35 @@ RNG_SystemRNG(void *dest, size_t maxLen)
size_t fileBytes = 0;
unsigned char *buffer = dest;
+#if defined(LINUX) && defined(__GLIBC__) && ((__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 25)))
+ int result;
+
+ while (fileBytes < maxLen) {
+ size_t getBytes = maxLen - fileBytes;
+ if (getBytes > GETENTROPY_MAX_BYTES) {
+ getBytes = GETENTROPY_MAX_BYTES;
+ }
+ result = getentropy(buffer, getBytes);
+ if (result == 0) { /* success */
+ fileBytes += getBytes;
+ buffer += getBytes;
+ } else {
+ break;
+ }
+ }
+ if (fileBytes == maxLen) { /* success */
+ return maxLen;
+ }
+ /* If we failed with an error other than ENOSYS, it means the destination
+ * buffer is not writeable. We don't need to try writing to it again. */
+ if (errno != ENOSYS) {
+ PORT_SetError(SEC_ERROR_NEED_RANDOM);
+ return 0;
+ }
+ /* ENOSYS means the kernel doesn't support getentropy()/getrandom().
+ * Reset the number of bytes to get and fall back to /dev/urandom. */
+ fileBytes = 0;
+#endif
fd = open("/dev/urandom", O_RDONLY);
if (fd < 0) {
PORT_SetError(SEC_ERROR_NEED_RANDOM);