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