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