ntp_crypto_rnd.c revision 290001
1/*
2 * Crypto-quality random number functions
3 *
4 * Author: Harlan Stenn, 2014
5 *
6 * This file is Copyright (c) 2014 by Network Time Foundation.
7 * BSD terms apply: see the file COPYRIGHT in the distribution root for details.
8 */
9
10#include "config.h"
11#include <sys/types.h>
12#ifdef HAVE_UNISTD_H
13# include <unistd.h>
14#endif
15#include <stdio.h>
16
17#include <l_stdlib.h>
18#include <ntp_random.h>
19
20#ifdef USE_OPENSSL_CRYPTO_RAND
21#include <openssl/err.h>
22#include <openssl/rand.h>
23
24int crypto_rand_init = 0;
25#else
26
27# ifndef HAVE_ARC4RANDOM_BUF
28static void
29arc4random_buf(void *buf, size_t nbytes);
30
31void
32evutil_secure_rng_get_bytes(void *buf, size_t nbytes);
33
34static void
35arc4random_buf(void *buf, size_t nbytes)
36{
37	evutil_secure_rng_get_bytes(buf, nbytes);
38	return;
39}
40# endif
41#endif
42
43/*
44 * As of late 2014, here's how we plan to provide cryptographic-quality
45 * random numbers:
46 *
47 * - If we are building with OpenSSL, use RAND_poll() and RAND_bytes().
48 * - Otherwise, use arc4random().
49 *
50 * Use of arc4random() can be forced using configure --disable-openssl-random
51 *
52 * We can count on arc4random existing, thru the OS or thru libevent.
53 * The quality of arc4random depends on the implementor.
54 *
55 * RAND_poll() doesn't show up until XXX.  If it's not present, we
56 * need to either provide our own or use arc4random().
57 */
58
59/*
60 * ntp_crypto_srandom:
61 *
62 * Initialize the random number generator, if needed by the underlying
63 * crypto random number generation mechanism.
64 */
65
66void
67ntp_crypto_srandom(
68	void
69	)
70{
71#ifdef USE_OPENSSL_CRYPTO_RAND
72	if (!crypto_rand_init) {
73		RAND_poll();
74		crypto_rand_init = 1;
75	}
76#else
77	/* No initialization needed for arc4random() */
78#endif
79}
80
81
82/*
83 * ntp_crypto_random_buf:
84 *
85 * Returns 0 on success, -1 on error.
86 */
87int
88ntp_crypto_random_buf(
89	void *buf,
90	size_t nbytes
91	)
92{
93#ifdef USE_OPENSSL_CRYPTO_RAND
94	int rc;
95
96	rc = RAND_bytes(buf, nbytes);
97	if (1 != rc) {
98		unsigned long err;
99		char *err_str;
100
101		err = ERR_get_error();
102		err_str = ERR_error_string(err, NULL);
103		/* XXX: Log the error */
104		(void)&err_str;
105
106		return -1;
107	}
108	return 0;
109#else
110	arc4random_buf(buf, nbytes);
111	return 0;
112#endif
113}
114