1 /* 2 * Crypto-quality random number functions 3 * 4 * Author: Harlan Stenn, 2014 5 * 6 * This file is Copyright (c) 2014 by Network Time Foundation. 7 * BSD terms apply: see the file COPYRIGHT in the distribution root for details. 8 */ 9 10 #include "config.h" 11 #include <sys/types.h> 12 #ifdef HAVE_UNISTD_H 13 # include <unistd.h> 14 #endif 15 #include <stdio.h> 16 17 #include <l_stdlib.h> 18 #include <ntp_random.h> 19 #include "safecast.h" 20 21 #ifdef USE_OPENSSL_CRYPTO_RAND 22 #include <openssl/err.h> 23 #include <openssl/rand.h> 24 25 int crypto_rand_init = 0; 26 #else 27 28 # ifndef HAVE_ARC4RANDOM_BUF 29 static void 30 arc4random_buf(void *buf, size_t nbytes); 31 32 void 33 evutil_secure_rng_get_bytes(void *buf, size_t nbytes); 34 35 static void 36 arc4random_buf(void *buf, size_t nbytes) 37 { 38 evutil_secure_rng_get_bytes(buf, nbytes); 39 return; 40 } 41 # endif 42 #endif 43 44 /* 45 * As of late 2014, here's how we plan to provide cryptographic-quality 46 * random numbers: 47 * 48 * - If we are building with OpenSSL, use RAND_poll() and RAND_bytes(). 49 * - Otherwise, use arc4random(). 50 * 51 * Use of arc4random() can be forced using configure --disable-openssl-random 52 * 53 * We can count on arc4random existing, thru the OS or thru libevent. 54 * The quality of arc4random depends on the implementor. 55 * 56 * RAND_poll() doesn't show up until XXX. If it's not present, we 57 * need to either provide our own or use arc4random(). 58 */ 59 60 /* 61 * ntp_crypto_srandom: 62 * 63 * Initialize the random number generator, if needed by the underlying 64 * crypto random number generation mechanism. 65 */ 66 67 void 68 ntp_crypto_srandom( 69 void 70 ) 71 { 72 #ifdef USE_OPENSSL_CRYPTO_RAND 73 if (!crypto_rand_init) { 74 RAND_poll(); 75 crypto_rand_init = 1; 76 } 77 #else 78 /* No initialization needed for arc4random() */ 79 #endif 80 } 81 82 83 /* 84 * ntp_crypto_random_buf: 85 * 86 * Returns 0 on success, -1 on error. 87 */ 88 int 89 ntp_crypto_random_buf( 90 void *buf, 91 size_t nbytes 92 ) 93 { 94 #ifdef USE_OPENSSL_CRYPTO_RAND 95 int rc; 96 97 rc = RAND_bytes(buf, size2int_chk(nbytes)); 98 if (1 != rc) { 99 unsigned long err; 100 char *err_str; 101 102 err = ERR_get_error(); 103 err_str = ERR_error_string(err, NULL); 104 /* XXX: Log the error */ 105 (void)&err_str; 106 107 return -1; 108 } 109 return 0; 110 #else 111 arc4random_buf(buf, nbytes); 112 return 0; 113 #endif 114 } 115