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