]> CyberLeo.Net >> Repos - FreeBSD/releng/9.3.git/blob - contrib/ntp/libntp/ntp_crypto_rnd.c
o Fix invalid TCP checksums with pf(4). [EN-16:02.pf]
[FreeBSD/releng/9.3.git] / contrib / ntp / libntp / ntp_crypto_rnd.c
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 #include "safecast.h"
20
21 #ifdef USE_OPENSSL_CRYPTO_RAND
22 #include <openssl/err.h>
23 #include <openssl/rand.h>
24
25 int crypto_rand_init = 0;
26 #else
27
28 # ifndef HAVE_ARC4RANDOM_BUF
29 static void
30 arc4random_buf(void *buf, size_t nbytes);
31
32 void
33 evutil_secure_rng_get_bytes(void *buf, size_t nbytes);
34
35 static void
36 arc4random_buf(void *buf, size_t nbytes)
37 {
38         evutil_secure_rng_get_bytes(buf, nbytes);
39         return;
40 }
41 # endif
42 #endif
43
44 /*
45  * As of late 2014, here's how we plan to provide cryptographic-quality
46  * random numbers:
47  * 
48  * - If we are building with OpenSSL, use RAND_poll() and RAND_bytes().
49  * - Otherwise, use arc4random().
50  * 
51  * Use of arc4random() can be forced using configure --disable-openssl-random
52  *
53  * We can count on arc4random existing, thru the OS or thru libevent.
54  * The quality of arc4random depends on the implementor.
55  * 
56  * RAND_poll() doesn't show up until XXX.  If it's not present, we
57  * need to either provide our own or use arc4random().
58  */
59
60 /*
61  * ntp_crypto_srandom:
62  *
63  * Initialize the random number generator, if needed by the underlying
64  * crypto random number generation mechanism.
65  */
66
67 void
68 ntp_crypto_srandom(
69         void
70         )
71 {
72 #ifdef USE_OPENSSL_CRYPTO_RAND
73         if (!crypto_rand_init) {
74                 RAND_poll();
75                 crypto_rand_init = 1;
76         }
77 #else
78         /* No initialization needed for arc4random() */
79 #endif
80 }
81
82
83 /*
84  * ntp_crypto_random_buf:
85  *
86  * Returns 0 on success, -1 on error.
87  */
88 int
89 ntp_crypto_random_buf(
90         void *buf,
91         size_t nbytes
92         )
93 {
94 #ifdef USE_OPENSSL_CRYPTO_RAND
95         int rc;
96
97         rc = RAND_bytes(buf, size2int_chk(nbytes));
98         if (1 != rc) {
99                 unsigned long err;
100                 char *err_str;
101
102                 err = ERR_get_error();
103                 err_str = ERR_error_string(err, NULL);
104                 /* XXX: Log the error */
105                 (void)&err_str;
106
107                 return -1;
108         }
109         return 0;
110 #else
111         arc4random_buf(buf, nbytes);
112         return 0;
113 #endif
114 }