1290001Sglebius/* 2290001Sglebius * Crypto-quality random number functions 3290001Sglebius * 4290001Sglebius * Author: Harlan Stenn, 2014 5290001Sglebius * 6290001Sglebius * This file is Copyright (c) 2014 by Network Time Foundation. 7290001Sglebius * BSD terms apply: see the file COPYRIGHT in the distribution root for details. 8290001Sglebius */ 9290001Sglebius 10290001Sglebius#include "config.h" 11290001Sglebius#include <sys/types.h> 12290001Sglebius#ifdef HAVE_UNISTD_H 13290001Sglebius# include <unistd.h> 14290001Sglebius#endif 15290001Sglebius#include <stdio.h> 16290001Sglebius 17290001Sglebius#include <l_stdlib.h> 18290001Sglebius#include <ntp_random.h> 19293896Sglebius#include "safecast.h" 20290001Sglebius 21290001Sglebius#ifdef USE_OPENSSL_CRYPTO_RAND 22290001Sglebius#include <openssl/err.h> 23290001Sglebius#include <openssl/rand.h> 24290001Sglebius 25290001Sglebiusint crypto_rand_init = 0; 26290001Sglebius#else 27290001Sglebius 28290001Sglebius# ifndef HAVE_ARC4RANDOM_BUF 29290001Sglebiusstatic void 30290001Sglebiusarc4random_buf(void *buf, size_t nbytes); 31290001Sglebius 32290001Sglebiusvoid 33290001Sglebiusevutil_secure_rng_get_bytes(void *buf, size_t nbytes); 34290001Sglebius 35290001Sglebiusstatic void 36290001Sglebiusarc4random_buf(void *buf, size_t nbytes) 37290001Sglebius{ 38290001Sglebius evutil_secure_rng_get_bytes(buf, nbytes); 39290001Sglebius return; 40290001Sglebius} 41290001Sglebius# endif 42290001Sglebius#endif 43290001Sglebius 44290001Sglebius/* 45290001Sglebius * As of late 2014, here's how we plan to provide cryptographic-quality 46290001Sglebius * random numbers: 47290001Sglebius * 48290001Sglebius * - If we are building with OpenSSL, use RAND_poll() and RAND_bytes(). 49290001Sglebius * - Otherwise, use arc4random(). 50290001Sglebius * 51290001Sglebius * Use of arc4random() can be forced using configure --disable-openssl-random 52290001Sglebius * 53290001Sglebius * We can count on arc4random existing, thru the OS or thru libevent. 54290001Sglebius * The quality of arc4random depends on the implementor. 55290001Sglebius * 56290001Sglebius * RAND_poll() doesn't show up until XXX. If it's not present, we 57290001Sglebius * need to either provide our own or use arc4random(). 58290001Sglebius */ 59290001Sglebius 60290001Sglebius/* 61290001Sglebius * ntp_crypto_srandom: 62290001Sglebius * 63290001Sglebius * Initialize the random number generator, if needed by the underlying 64290001Sglebius * crypto random number generation mechanism. 65290001Sglebius */ 66290001Sglebius 67290001Sglebiusvoid 68290001Sglebiusntp_crypto_srandom( 69290001Sglebius void 70290001Sglebius ) 71290001Sglebius{ 72290001Sglebius#ifdef USE_OPENSSL_CRYPTO_RAND 73290001Sglebius if (!crypto_rand_init) { 74290001Sglebius RAND_poll(); 75290001Sglebius crypto_rand_init = 1; 76290001Sglebius } 77290001Sglebius#else 78290001Sglebius /* No initialization needed for arc4random() */ 79290001Sglebius#endif 80290001Sglebius} 81290001Sglebius 82290001Sglebius 83290001Sglebius/* 84290001Sglebius * ntp_crypto_random_buf: 85290001Sglebius * 86290001Sglebius * Returns 0 on success, -1 on error. 87290001Sglebius */ 88290001Sglebiusint 89290001Sglebiusntp_crypto_random_buf( 90290001Sglebius void *buf, 91290001Sglebius size_t nbytes 92290001Sglebius ) 93290001Sglebius{ 94290001Sglebius#ifdef USE_OPENSSL_CRYPTO_RAND 95290001Sglebius int rc; 96290001Sglebius 97293896Sglebius rc = RAND_bytes(buf, size2int_chk(nbytes)); 98290001Sglebius if (1 != rc) { 99290001Sglebius unsigned long err; 100290001Sglebius char *err_str; 101290001Sglebius 102290001Sglebius err = ERR_get_error(); 103290001Sglebius err_str = ERR_error_string(err, NULL); 104290001Sglebius /* XXX: Log the error */ 105290001Sglebius (void)&err_str; 106290001Sglebius 107290001Sglebius return -1; 108290001Sglebius } 109290001Sglebius return 0; 110290001Sglebius#else 111290001Sglebius arc4random_buf(buf, nbytes); 112290001Sglebius return 0; 113290001Sglebius#endif 114290001Sglebius} 115