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