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 27int crypto_rand_init = 0; 28#else 29 30# ifndef HAVE_ARC4RANDOM_BUF 31static void 32arc4random_buf(void *buf, size_t nbytes); 33 34void 35evutil_secure_rng_get_bytes(void *buf, size_t nbytes); 36 37static void 38arc4random_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 69void 70ntp_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 */ 90int 91ntp_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