aboutsummaryrefslogtreecommitdiff
path: root/contrib/ntp/libntp/ntp_crypto_rnd.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/ntp/libntp/ntp_crypto_rnd.c')
-rw-r--r--contrib/ntp/libntp/ntp_crypto_rnd.c115
1 files changed, 115 insertions, 0 deletions
diff --git a/contrib/ntp/libntp/ntp_crypto_rnd.c b/contrib/ntp/libntp/ntp_crypto_rnd.c
new file mode 100644
index 000000000000..5fe7382efb79
--- /dev/null
+++ b/contrib/ntp/libntp/ntp_crypto_rnd.c
@@ -0,0 +1,115 @@
+/*
+ * Crypto-quality random number functions
+ *
+ * Author: Harlan Stenn, 2014
+ *
+ * This file is Copyright (c) 2014 by Network Time Foundation.
+ * BSD terms apply: see the file COPYRIGHT in the distribution root for details.
+ */
+
+#include "config.h"
+#include <sys/types.h>
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+#include <stdio.h>
+
+#include <ntp_stdlib.h>
+#include <ntp_random.h>
+#include "safecast.h"
+
+#ifdef USE_OPENSSL_CRYPTO_RAND
+#include <openssl/err.h>
+#include <openssl/rand.h>
+
+int crypto_rand_init = 0;
+#elif !defined(HAVE_ARC4RANDOM_BUF)
+#include <event2/util.h>
+#endif
+
+int crypto_rand_ok = 0;
+
+/*
+ * As of late 2014, here's how we plan to provide cryptographic-quality
+ * random numbers:
+ *
+ * - If we are building with OpenSSL, use RAND_poll() and RAND_bytes().
+ * - Otherwise, use arc4random().
+ *
+ * Use of arc4random() can be forced using configure options
+ * --disable-openssl-random or --without-crypto.
+ *
+ * We can count on arc4random existing, thru the OS or thru libevent.
+ * The quality of arc4random depends on the implementor.
+ *
+ * RAND_poll() doesn't show up until XXX. If it's not present, we
+ * need to either provide our own or use arc4random().
+ */
+
+ /*
+ * ntp_crypto_srandom:
+ *
+ * Initialize the random number generator, if needed by the underlying
+ * crypto random number generation mechanism.
+ */
+
+void
+ntp_crypto_srandom(
+ void
+)
+{
+#ifdef USE_OPENSSL_CRYPTO_RAND
+ if (!crypto_rand_init) {
+ if (RAND_poll())
+ crypto_rand_ok = 1;
+ crypto_rand_init = 1;
+ }
+#elif HAVE_ARC4RANDOM_BUF
+ /*
+ * arc4random_buf has no error return and needs no seeding nor reseeding.
+ */
+ crypto_rand_ok = 1;
+#else
+ /*
+ * Explicitly init libevent secure RNG to make sure it seeds.
+ * This is the only way we can tell if it can successfully get
+ * entropy from the system.
+ */
+ if (!evutil_secure_rng_init())
+ crypto_rand_ok = 1;
+#endif
+}
+
+
+/*
+ * ntp_crypto_random_buf: Used by ntp-keygen
+ *
+ * Returns 0 on success, -1 on error.
+ */
+int
+ntp_crypto_random_buf(
+ void *buf,
+ size_t nbytes
+ )
+{
+ if (!crypto_rand_ok)
+ return -1;
+
+#if defined(USE_OPENSSL_CRYPTO_RAND)
+ if (1 != RAND_bytes(buf, size2int_chk(nbytes))) {
+ unsigned long err;
+ char *err_str;
+
+ err = ERR_get_error();
+ err_str = ERR_error_string(err, NULL);
+ msyslog(LOG_ERR, "RAND_bytes failed: %s", err_str);
+
+ return -1;
+ }
+#elif defined(HAVE_ARC4RANDOM_BUF)
+ arc4random_buf(buf, nbytes);
+#else
+ evutil_secure_rng_get_bytes(buf, nbytes);
+#endif
+ return 0;
+}