xref: /netbsd-src/external/bsd/ntp/dist/libntp/ntp_crypto_rnd.c (revision f89f6560d453f5e37386cc7938c072d2f528b9fa)
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