xref: /freebsd/contrib/ntp/libntp/ntp_crypto_rnd.c (revision a466cc55)
12b15cb3dSCy Schubert /*
22b15cb3dSCy Schubert  * Crypto-quality random number functions
32b15cb3dSCy Schubert  *
42b15cb3dSCy Schubert  * Author: Harlan Stenn, 2014
52b15cb3dSCy Schubert  *
62b15cb3dSCy Schubert  * This file is Copyright (c) 2014 by Network Time Foundation.
72b15cb3dSCy Schubert  * BSD terms apply: see the file COPYRIGHT in the distribution root for details.
82b15cb3dSCy Schubert  */
92b15cb3dSCy Schubert 
102b15cb3dSCy Schubert #include "config.h"
112b15cb3dSCy Schubert #include <sys/types.h>
122b15cb3dSCy Schubert #ifdef HAVE_UNISTD_H
132b15cb3dSCy Schubert # include <unistd.h>
142b15cb3dSCy Schubert #endif
152b15cb3dSCy Schubert #include <stdio.h>
162b15cb3dSCy Schubert 
17*a466cc55SCy Schubert #include <ntp_stdlib.h>
182b15cb3dSCy Schubert #include <ntp_random.h>
193311ff84SXin LI #include "safecast.h"
202b15cb3dSCy Schubert 
212b15cb3dSCy Schubert #ifdef USE_OPENSSL_CRYPTO_RAND
222b15cb3dSCy Schubert #include <openssl/err.h>
232b15cb3dSCy Schubert #include <openssl/rand.h>
242b15cb3dSCy Schubert 
252b15cb3dSCy Schubert int crypto_rand_init = 0;
26*a466cc55SCy Schubert #elif !defined(HAVE_ARC4RANDOM_BUF)
27*a466cc55SCy Schubert #include <event2/util.h>
282b15cb3dSCy Schubert #endif
29*a466cc55SCy Schubert 
30*a466cc55SCy Schubert int crypto_rand_ok = 0;
312b15cb3dSCy Schubert 
322b15cb3dSCy Schubert /*
332b15cb3dSCy Schubert  * As of late 2014, here's how we plan to provide cryptographic-quality
342b15cb3dSCy Schubert  * random numbers:
352b15cb3dSCy Schubert  *
362b15cb3dSCy Schubert  * - If we are building with OpenSSL, use RAND_poll() and RAND_bytes().
372b15cb3dSCy Schubert  * - Otherwise, use arc4random().
382b15cb3dSCy Schubert  *
39*a466cc55SCy Schubert  * Use of arc4random() can be forced using configure options
40*a466cc55SCy Schubert  * --disable-openssl-random or --without-crypto.
412b15cb3dSCy Schubert  *
422b15cb3dSCy Schubert  * We can count on arc4random existing, thru the OS or thru libevent.
432b15cb3dSCy Schubert  * The quality of arc4random depends on the implementor.
442b15cb3dSCy Schubert  *
452b15cb3dSCy Schubert  * RAND_poll() doesn't show up until XXX.  If it's not present, we
462b15cb3dSCy Schubert  * need to either provide our own or use arc4random().
472b15cb3dSCy Schubert  */
482b15cb3dSCy Schubert 
492b15cb3dSCy Schubert  /*
502b15cb3dSCy Schubert   * ntp_crypto_srandom:
512b15cb3dSCy Schubert   *
522b15cb3dSCy Schubert   * Initialize the random number generator, if needed by the underlying
532b15cb3dSCy Schubert   * crypto random number generation mechanism.
542b15cb3dSCy Schubert   */
552b15cb3dSCy Schubert 
562b15cb3dSCy Schubert void
ntp_crypto_srandom(void)572b15cb3dSCy Schubert ntp_crypto_srandom(
582b15cb3dSCy Schubert 	void
592b15cb3dSCy Schubert )
602b15cb3dSCy Schubert {
612b15cb3dSCy Schubert #ifdef USE_OPENSSL_CRYPTO_RAND
622b15cb3dSCy Schubert 	if (!crypto_rand_init) {
63*a466cc55SCy Schubert 		if (RAND_poll())
64*a466cc55SCy Schubert 			crypto_rand_ok = 1;
652b15cb3dSCy Schubert 		crypto_rand_init = 1;
662b15cb3dSCy Schubert 	}
67*a466cc55SCy Schubert #elif HAVE_ARC4RANDOM_BUF
68*a466cc55SCy Schubert 	/*
69*a466cc55SCy Schubert 	 * arc4random_buf has no error return and needs no seeding nor reseeding.
70*a466cc55SCy Schubert 	 */
71*a466cc55SCy Schubert 	crypto_rand_ok = 1;
722b15cb3dSCy Schubert #else
73*a466cc55SCy Schubert 	/*
74*a466cc55SCy Schubert 	 * Explicitly init libevent secure RNG to make sure it seeds.
75*a466cc55SCy Schubert 	 * This is the only way we can tell if it can successfully get
76*a466cc55SCy Schubert 	 * entropy from the system.
77*a466cc55SCy Schubert 	 */
78*a466cc55SCy Schubert 	if (!evutil_secure_rng_init())
79*a466cc55SCy Schubert 		crypto_rand_ok = 1;
802b15cb3dSCy Schubert #endif
812b15cb3dSCy Schubert }
822b15cb3dSCy Schubert 
832b15cb3dSCy Schubert 
842b15cb3dSCy Schubert /*
85*a466cc55SCy Schubert  * ntp_crypto_random_buf:  Used by ntp-keygen
862b15cb3dSCy Schubert  *
872b15cb3dSCy Schubert  * Returns 0 on success, -1 on error.
882b15cb3dSCy Schubert  */
892b15cb3dSCy Schubert int
ntp_crypto_random_buf(void * buf,size_t nbytes)902b15cb3dSCy Schubert ntp_crypto_random_buf(
912b15cb3dSCy Schubert 	void *buf,
922b15cb3dSCy Schubert 	size_t nbytes
932b15cb3dSCy Schubert 	)
942b15cb3dSCy Schubert {
95*a466cc55SCy Schubert 	if (!crypto_rand_ok)
96*a466cc55SCy Schubert 		return -1;
972b15cb3dSCy Schubert 
98*a466cc55SCy Schubert #if defined(USE_OPENSSL_CRYPTO_RAND)
99*a466cc55SCy Schubert 	if (1 != RAND_bytes(buf, size2int_chk(nbytes))) {
1002b15cb3dSCy Schubert 		unsigned long err;
1012b15cb3dSCy Schubert 		char *err_str;
1022b15cb3dSCy Schubert 
1032b15cb3dSCy Schubert 		err = ERR_get_error();
1042b15cb3dSCy Schubert 		err_str = ERR_error_string(err, NULL);
105*a466cc55SCy Schubert 		msyslog(LOG_ERR, "RAND_bytes failed: %s", err_str);
1062b15cb3dSCy Schubert 
1072b15cb3dSCy Schubert 		return -1;
1082b15cb3dSCy Schubert 	}
109*a466cc55SCy Schubert #elif defined(HAVE_ARC4RANDOM_BUF)
1102b15cb3dSCy Schubert 	arc4random_buf(buf, nbytes);
111*a466cc55SCy Schubert #else
112*a466cc55SCy Schubert 	evutil_secure_rng_get_bytes(buf, nbytes);
1132b15cb3dSCy Schubert #endif
114*a466cc55SCy Schubert 	return 0;
1152b15cb3dSCy Schubert }
116