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