Line data Source code
1 : /* random-system.c - wrapper around the system's RNG
2 : * Copyright (C) 2012 Free Software Foundation, Inc.
3 : *
4 : * This file is part of Libgcrypt.
5 : *
6 : * Libgcrypt is free software; you can redistribute it and/or modify
7 : * it under the terms of the GNU Lesser General Public License as
8 : * published by the Free Software Foundation; either version 2.1 of
9 : * the License, or (at your option) any later version.
10 : *
11 : * Libgcrypt is distributed in the hope that it will be useful,
12 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : * GNU Lesser General Public License for more details.
15 : *
16 : * You should have received a copy of the GNU Lesser General Public
17 : * License along with this program; if not, see <http://www.gnu.org/licenses/>.
18 : */
19 :
20 : /*
21 : This RNG is merely wrapper around the system's native RNG. For
22 : example on Unix systems it directly uses /dev/{u,}random.
23 : */
24 :
25 : #include <config.h>
26 : #include <stdio.h>
27 : #include <stdlib.h>
28 : #include <errno.h>
29 : #include <sys/types.h>
30 : #include <unistd.h>
31 : #ifdef HAVE_GETTIMEOFDAY
32 : #include <sys/time.h>
33 : #endif
34 :
35 : #include "g10lib.h"
36 : #include "random.h"
37 : #include "rand-internal.h"
38 :
39 : /* This is the lock we use to serialize access to this RNG. The extra
40 : integer variable is only used to check the locking state; that is,
41 : it is not meant to be thread-safe but merely as a failsafe feature
42 : to assert proper locking. */
43 : GPGRT_LOCK_DEFINE (system_rng_lock);
44 : static int system_rng_is_locked;
45 :
46 :
47 : /* --- Local prototypes --- */
48 :
49 :
50 :
51 :
52 : /* --- Functions --- */
53 :
54 : /* Basic initialization is required to initialize mutexes and
55 : do a few checks on the implementation. */
56 : static void
57 8 : basic_initialization (void)
58 : {
59 : static int initialized;
60 :
61 8 : if (initialized)
62 6 : return;
63 2 : initialized = 1;
64 :
65 2 : system_rng_is_locked = 0;
66 :
67 : /* Make sure that we are still using the values we traditionally
68 : used for the random levels. */
69 : gcry_assert (GCRY_WEAK_RANDOM == 0
70 : && GCRY_STRONG_RANDOM == 1
71 : && GCRY_VERY_STRONG_RANDOM == 2);
72 :
73 : }
74 :
75 :
76 : /* Acquire the system_rng_lock. */
77 : static void
78 6 : lock_rng (void)
79 : {
80 : gpg_err_code_t rc;
81 :
82 6 : rc = gpgrt_lock_lock (&system_rng_lock);
83 6 : if (rc)
84 0 : log_fatal ("failed to acquire the System RNG lock: %s\n",
85 : gpg_strerror (rc));
86 6 : system_rng_is_locked = 1;
87 6 : }
88 :
89 :
90 : /* Release the system_rng_lock. */
91 : static void
92 6 : unlock_rng (void)
93 : {
94 : gpg_err_code_t rc;
95 :
96 6 : system_rng_is_locked = 0;
97 6 : rc = gpgrt_lock_unlock (&system_rng_lock);
98 6 : if (rc)
99 0 : log_fatal ("failed to release the System RNG lock: %s\n",
100 : gpg_strerror (rc));
101 6 : }
102 :
103 :
104 : /* Helper variables for read_cb().
105 :
106 : The _gcry_rnd*_gather_random interface does not allow to provide a
107 : data pointer. Thus we need to use a global variable for
108 : communication. However, the then required locking is anyway a good
109 : idea because it does not make sense to have several readers of (say
110 : /dev/random). It is easier to serve them one after the other. */
111 : static unsigned char *read_cb_buffer; /* The buffer. */
112 : static size_t read_cb_size; /* Size of the buffer. */
113 : static size_t read_cb_len; /* Used length. */
114 :
115 :
116 : /* Callback for _gcry_rnd*_gather_random. */
117 : static void
118 6 : read_cb (const void *buffer, size_t length, enum random_origins origin)
119 : {
120 6 : const unsigned char *p = buffer;
121 :
122 : (void)origin;
123 :
124 6 : gcry_assert (system_rng_is_locked);
125 6 : gcry_assert (read_cb_buffer);
126 :
127 : /* Note that we need to protect against gatherers returning more
128 : than the requested bytes (e.g. rndw32). */
129 36 : while (length-- && read_cb_len < read_cb_size)
130 : {
131 24 : read_cb_buffer[read_cb_len++] = *p++;
132 : }
133 6 : }
134 :
135 :
136 : /* Fill BUFFER with LENGTH bytes of random at quality LEVEL. The
137 : function either succeeds or terminates the process in case of a
138 : fatal error. */
139 : static void
140 6 : get_random (void *buffer, size_t length, int level)
141 : {
142 : int rc;
143 :
144 6 : gcry_assert (buffer);
145 :
146 6 : read_cb_buffer = buffer;
147 6 : read_cb_size = length;
148 6 : read_cb_len = 0;
149 :
150 : #if USE_RNDLINUX
151 6 : rc = _gcry_rndlinux_gather_random (read_cb, 0, length, level);
152 : #elif USE_RNDUNIX
153 : rc = _gcry_rndunix_gather_random (read_cb, 0, length, level);
154 : #elif USE_RNDW32
155 : do
156 : {
157 : rc = _gcry_rndw32_gather_random (read_cb, 0, length, level);
158 : }
159 : while (rc >= 0 && read_cb_len < read_cb_size);
160 : #else
161 : rc = -1;
162 : #endif
163 :
164 6 : if (rc < 0 || read_cb_len != read_cb_size)
165 : {
166 0 : log_fatal ("error reading random from system RNG (rc=%d)\n", rc);
167 : }
168 6 : }
169 :
170 :
171 :
172 : /* --- Public Functions --- */
173 :
174 : /* Initialize this random subsystem. If FULL is false, this function
175 : merely calls the basic initialization of the module and does not do
176 : anything more. Doing this is not really required but when running
177 : in a threaded environment we might get a race condition
178 : otherwise. */
179 : void
180 8 : _gcry_rngsystem_initialize (int full)
181 : {
182 8 : basic_initialization ();
183 8 : if (!full)
184 2 : return;
185 : /* Nothing more to initialize. */
186 6 : return;
187 : }
188 :
189 :
190 : /* Try to close the FDs of the random gather module. This is
191 : currently only implemented for rndlinux. */
192 : void
193 0 : _gcry_rngsystem_close_fds (void)
194 : {
195 0 : lock_rng ();
196 : #if USE_RNDLINUX
197 0 : _gcry_rndlinux_gather_random (NULL, 0, 0, 0);
198 : #endif
199 0 : unlock_rng ();
200 0 : }
201 :
202 :
203 : /* Print some statistics about the RNG. */
204 : void
205 0 : _gcry_rngsystem_dump_stats (void)
206 : {
207 : /* Not yet implemented. */
208 0 : }
209 :
210 :
211 : /* This function returns true if no real RNG is available or the
212 : quality of the RNG has been degraded for test purposes. */
213 : int
214 0 : _gcry_rngsystem_is_faked (void)
215 : {
216 0 : return 0; /* Faked random is not supported. */
217 : }
218 :
219 :
220 : /* Add BUFLEN bytes from BUF to the internal random pool. QUALITY
221 : should be in the range of 0..100 to indicate the goodness of the
222 : entropy added, or -1 for goodness not known. */
223 : gcry_error_t
224 0 : _gcry_rngsystem_add_bytes (const void *buf, size_t buflen, int quality)
225 : {
226 : (void)buf;
227 : (void)buflen;
228 : (void)quality;
229 0 : return 0; /* Not implemented. */
230 : }
231 :
232 :
233 : /* Public function to fill the buffer with LENGTH bytes of
234 : cryptographically strong random bytes. Level GCRY_WEAK_RANDOM is
235 : here mapped to GCRY_STRONG_RANDOM, GCRY_STRONG_RANDOM is strong
236 : enough for most usage, GCRY_VERY_STRONG_RANDOM is good for key
237 : generation stuff but may be very slow. */
238 : void
239 6 : _gcry_rngsystem_randomize (void *buffer, size_t length,
240 : enum gcry_random_level level)
241 : {
242 6 : _gcry_rngsystem_initialize (1); /* Auto-initialize if needed. */
243 :
244 6 : if (level != GCRY_VERY_STRONG_RANDOM)
245 6 : level = GCRY_STRONG_RANDOM;
246 :
247 6 : lock_rng ();
248 6 : get_random (buffer, length, level);
249 6 : unlock_rng ();
250 6 : }
|