/src/libgcrypt/random/random-system.c
Line | Count | Source (jump to first uncovered line) |
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 | | basic_initialization (void) |
58 | 0 | { |
59 | 0 | static int initialized; |
60 | |
|
61 | 0 | if (initialized) |
62 | 0 | return; |
63 | 0 | initialized = 1; |
64 | |
|
65 | 0 | 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 | 0 | gcry_assert (GCRY_WEAK_RANDOM == 0 |
70 | 0 | && GCRY_STRONG_RANDOM == 1 |
71 | 0 | && GCRY_VERY_STRONG_RANDOM == 2); |
72 | |
|
73 | 0 | } |
74 | | |
75 | | |
76 | | /* Acquire the system_rng_lock. */ |
77 | | static void |
78 | | lock_rng (void) |
79 | 0 | { |
80 | 0 | gpg_err_code_t rc; |
81 | |
|
82 | 0 | rc = gpgrt_lock_lock (&system_rng_lock); |
83 | 0 | if (rc) |
84 | 0 | log_fatal ("failed to acquire the System RNG lock: %s\n", |
85 | 0 | gpg_strerror (rc)); |
86 | 0 | system_rng_is_locked = 1; |
87 | 0 | } |
88 | | |
89 | | |
90 | | /* Release the system_rng_lock. */ |
91 | | static void |
92 | | unlock_rng (void) |
93 | 0 | { |
94 | 0 | gpg_err_code_t rc; |
95 | |
|
96 | 0 | system_rng_is_locked = 0; |
97 | 0 | rc = gpgrt_lock_unlock (&system_rng_lock); |
98 | 0 | if (rc) |
99 | 0 | log_fatal ("failed to release the System RNG lock: %s\n", |
100 | 0 | gpg_strerror (rc)); |
101 | 0 | } |
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 | | read_cb (const void *buffer, size_t length, enum random_origins origin) |
119 | 0 | { |
120 | 0 | const unsigned char *p = buffer; |
121 | |
|
122 | 0 | (void)origin; |
123 | |
|
124 | 0 | gcry_assert (system_rng_is_locked); |
125 | 0 | 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 | 0 | while (length-- && read_cb_len < read_cb_size) |
130 | 0 | { |
131 | 0 | read_cb_buffer[read_cb_len++] = *p++; |
132 | 0 | } |
133 | 0 | } |
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 | | get_random (void *buffer, size_t length, int level) |
141 | 0 | { |
142 | 0 | int rc; |
143 | |
|
144 | 0 | gcry_assert (buffer); |
145 | | |
146 | 0 | read_cb_buffer = buffer; |
147 | 0 | read_cb_size = length; |
148 | 0 | read_cb_len = 0; |
149 | |
|
150 | 0 | #if USE_RNDGETENTROPY |
151 | 0 | rc = _gcry_rndgetentropy_gather_random (read_cb, 0, length, level); |
152 | | #elif USE_RNDOLDLINUX |
153 | | rc = _gcry_rndoldlinux_gather_random (read_cb, 0, length, level); |
154 | | #elif USE_RNDUNIX |
155 | | rc = _gcry_rndunix_gather_random (read_cb, 0, length, level); |
156 | | #elif USE_RNDW32 |
157 | | do |
158 | | { |
159 | | rc = _gcry_rndw32_gather_random (read_cb, 0, length, level); |
160 | | } |
161 | | while (rc >= 0 && read_cb_len < read_cb_size); |
162 | | #else |
163 | | rc = -1; |
164 | | #endif |
165 | |
|
166 | 0 | if (rc < 0 || read_cb_len != read_cb_size) |
167 | 0 | { |
168 | 0 | log_fatal ("error reading random from system RNG (rc=%d)\n", rc); |
169 | 0 | } |
170 | 0 | } |
171 | | |
172 | | |
173 | | |
174 | | /* --- Public Functions --- */ |
175 | | |
176 | | /* Initialize this random subsystem. If FULL is false, this function |
177 | | merely calls the basic initialization of the module and does not do |
178 | | anything more. Doing this is not really required but when running |
179 | | in a threaded environment we might get a race condition |
180 | | otherwise. */ |
181 | | void |
182 | | _gcry_rngsystem_initialize (int full) |
183 | 0 | { |
184 | 0 | basic_initialization (); |
185 | 0 | if (!full) |
186 | 0 | return; |
187 | | /* Nothing more to initialize. */ |
188 | 0 | return; |
189 | 0 | } |
190 | | |
191 | | |
192 | | /* Try to close the FDs of the random gather module. This is |
193 | | currently only implemented for rndgetentropy/rndoldlinux. */ |
194 | | void |
195 | | _gcry_rngsystem_close_fds (void) |
196 | 0 | { |
197 | 0 | lock_rng (); |
198 | 0 | #if USE_RNDGETENTROPY |
199 | 0 | _gcry_rndgetentropy_gather_random (NULL, 0, 0, 0); |
200 | 0 | #endif |
201 | | #if USE_RNDOLDLINUX |
202 | | _gcry_rndoldlinux_gather_random (NULL, 0, 0, 0); |
203 | | #endif |
204 | 0 | unlock_rng (); |
205 | 0 | } |
206 | | |
207 | | |
208 | | /* Print some statistics about the RNG. */ |
209 | | void |
210 | | _gcry_rngsystem_dump_stats (void) |
211 | 0 | { |
212 | | /* Not yet implemented. */ |
213 | 0 | } |
214 | | |
215 | | |
216 | | /* This function returns true if no real RNG is available or the |
217 | | quality of the RNG has been degraded for test purposes. */ |
218 | | int |
219 | | _gcry_rngsystem_is_faked (void) |
220 | 0 | { |
221 | 0 | return 0; /* Faked random is not supported. */ |
222 | 0 | } |
223 | | |
224 | | |
225 | | /* Add BUFLEN bytes from BUF to the internal random pool. QUALITY |
226 | | should be in the range of 0..100 to indicate the goodness of the |
227 | | entropy added, or -1 for goodness not known. */ |
228 | | gcry_error_t |
229 | | _gcry_rngsystem_add_bytes (const void *buf, size_t buflen, int quality) |
230 | 0 | { |
231 | 0 | (void)buf; |
232 | 0 | (void)buflen; |
233 | 0 | (void)quality; |
234 | 0 | return 0; /* Not implemented. */ |
235 | 0 | } |
236 | | |
237 | | |
238 | | /* Public function to fill the buffer with LENGTH bytes of |
239 | | cryptographically strong random bytes. Level GCRY_WEAK_RANDOM is |
240 | | here mapped to GCRY_STRONG_RANDOM, GCRY_STRONG_RANDOM is strong |
241 | | enough for most usage, GCRY_VERY_STRONG_RANDOM is good for key |
242 | | generation stuff but may be very slow. */ |
243 | | void |
244 | | _gcry_rngsystem_randomize (void *buffer, size_t length, |
245 | | enum gcry_random_level level) |
246 | 0 | { |
247 | 0 | _gcry_rngsystem_initialize (1); /* Auto-initialize if needed. */ |
248 | |
|
249 | 0 | if (level != GCRY_VERY_STRONG_RANDOM) |
250 | 0 | level = GCRY_STRONG_RANDOM; |
251 | |
|
252 | 0 | lock_rng (); |
253 | 0 | get_random (buffer, length, level); |
254 | 0 | unlock_rng (); |
255 | 0 | } |