aboutsummaryrefslogtreecommitdiff
path: root/libntp/ntp_crypto_rnd.c
blob: 96348f2e8696e1a07db3142287aea22436052419 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
/*
 * Crypto-quality random number functions
 *
 * Author: Harlan Stenn, 2014
 *
 * This file is Copyright (c) 2014 by Network Time Foundation.
 * BSD terms apply: see the file COPYRIGHT in the distribution root for details.
 */

#include "config.h"
#include <sys/types.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#include <stdio.h>

#include <l_stdlib.h>
#include <ntp_random.h>

#ifdef USE_OPENSSL_CRYPTO_RAND
#include <openssl/err.h>
#include <openssl/rand.h>

int crypto_rand_init = 0;
#else

# ifndef HAVE_ARC4RANDOM_BUF
static void
arc4random_buf(void *buf, size_t nbytes);

void
evutil_secure_rng_get_bytes(void *buf, size_t nbytes);

static void
arc4random_buf(void *buf, size_t nbytes)
{
	evutil_secure_rng_get_bytes(buf, nbytes);
	return;
}
# endif
#endif

/*
 * As of late 2014, here's how we plan to provide cryptographic-quality
 * random numbers:
 * 
 * - If we are building with OpenSSL, use RAND_poll() and RAND_bytes().
 * - Otherwise, use arc4random().
 * 
 * Use of arc4random() can be forced using configure --disable-openssl-random
 *
 * We can count on arc4random existing, thru the OS or thru libevent.
 * The quality of arc4random depends on the implementor.
 * 
 * RAND_poll() doesn't show up until XXX.  If it's not present, we
 * need to either provide our own or use arc4random().
 */

/*
 * ntp_crypto_srandom:
 *
 * Initialize the random number generator, if needed by the underlying
 * crypto random number generation mechanism.
 */

void
ntp_crypto_srandom(
	void
	)
{
#ifdef USE_OPENSSL_CRYPTO_RAND
	if (!crypto_rand_init) {
		RAND_poll();
		crypto_rand_init = 1;
	}
#else
	/* No initialization needed for arc4random() */
#endif
}


/*
 * ntp_crypto_random_buf:
 *
 * Returns 0 on success, -1 on error.
 */
int
ntp_crypto_random_buf(
	void *buf,
	size_t nbytes
	)
{
#ifdef USE_OPENSSL_CRYPTO_RAND
	int rc;

	rc = RAND_bytes(buf, nbytes);
	if (1 != rc) {
		unsigned long err;
		char *err_str;

		err = ERR_get_error();
		err_str = ERR_error_string(err, NULL);
		/* XXX: Log the error */
		(void)&err_str;

		return -1;
	}
	return 0;
#else
	arc4random_buf(buf, nbytes);
	return 0;
#endif
}