random: Add a feature to close device file descriptors.
[libgcrypt.git] / random / random-system.c
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 #include "ath.h"
39
40 /* This is the lock we use to serialize access to this RNG.  The extra
41    integer variable is only used to check the locking state; that is,
42    it is not meant to be thread-safe but merely as a failsafe feature
43    to assert proper locking.  */
44 static ath_mutex_t system_rng_lock;
45 static int system_rng_is_locked;
46
47
48 /* --- Local prototypes ---  */
49
50
51
52 \f
53 /* --- Functions  --- */
54
55 /* Basic initialization is required to initialize mutexes and
56    do a few checks on the implementation.  */
57 static void
58 basic_initialization (void)
59 {
60   static int initialized;
61   int my_errno;
62
63   if (initialized)
64     return;
65   initialized = 1;
66
67   my_errno = ath_mutex_init (&system_rng_lock);
68   if (my_errno)
69     log_fatal ("failed to create the System RNG lock: %s\n",
70                strerror (my_errno));
71   system_rng_is_locked = 0;
72
73   /* Make sure that we are still using the values we traditionally
74      used for the random levels.  */
75   gcry_assert (GCRY_WEAK_RANDOM == 0
76                && GCRY_STRONG_RANDOM == 1
77                && GCRY_VERY_STRONG_RANDOM == 2);
78
79 }
80
81
82 /* Acquire the system_rng_lock.  */
83 static void
84 lock_rng (void)
85 {
86   int my_errno;
87
88   my_errno = ath_mutex_lock (&system_rng_lock);
89   if (my_errno)
90     log_fatal ("failed to acquire the System RNG lock: %s\n",
91                strerror (my_errno));
92   system_rng_is_locked = 1;
93 }
94
95
96 /* Release the system_rng_lock.  */
97 static void
98 unlock_rng (void)
99 {
100   int my_errno;
101
102   system_rng_is_locked = 0;
103   my_errno = ath_mutex_unlock (&system_rng_lock);
104   if (my_errno)
105     log_fatal ("failed to release the System RNG lock: %s\n",
106                strerror (my_errno));
107 }
108
109
110 /* Helper variables for read_cb().
111
112    The _gcry_rnd*_gather_random interface does not allow to provide a
113    data pointer.  Thus we need to use a global variable for
114    communication.  However, the then required locking is anyway a good
115    idea because it does not make sense to have several readers of (say
116    /dev/random).  It is easier to serve them one after the other.  */
117 static unsigned char *read_cb_buffer;   /* The buffer.  */
118 static size_t         read_cb_size;     /* Size of the buffer.  */
119 static size_t         read_cb_len;      /* Used length.  */
120
121
122 /* Callback for _gcry_rnd*_gather_random.  */
123 static void
124 read_cb (const void *buffer, size_t length, enum random_origins origin)
125 {
126   const unsigned char *p = buffer;
127
128   (void)origin;
129
130   gcry_assert (system_rng_is_locked);
131   gcry_assert (read_cb_buffer);
132
133   /* Note that we need to protect against gatherers returning more
134      than the requested bytes (e.g. rndw32).  */
135   while (length-- && read_cb_len < read_cb_size)
136     {
137       read_cb_buffer[read_cb_len++] = *p++;
138     }
139 }
140
141
142 /* Fill BUFFER with LENGTH bytes of random at quality LEVEL.  The
143    function either succeeds or terminates the process in case of a
144    fatal error. */
145 static void
146 get_random (void *buffer, size_t length, int level)
147 {
148   int rc;
149
150   gcry_assert (buffer);
151
152   read_cb_buffer = buffer;
153   read_cb_size   = length;
154   read_cb_len    = 0;
155
156 #if USE_RNDLINUX
157   rc = _gcry_rndlinux_gather_random (read_cb, 0, length, level);
158 #elif USE_RNDUNIX
159   rc = _gcry_rndunix_gather_random (read_cb, 0, length, level);
160 #elif USE_RNDW32
161   do
162     {
163       rc = _gcry_rndw32_gather_random (read_cb, 0, length, level);
164     }
165   while (rc >= 0 && read_cb_len < read_cb_size);
166 #else
167   rc = -1;
168 #endif
169
170   if (rc < 0 || read_cb_len != read_cb_size)
171     {
172       log_fatal ("error reading random from system RNG (rc=%d)\n", rc);
173     }
174 }
175
176
177 \f
178 /* --- Public Functions --- */
179
180 /* Initialize this random subsystem.  If FULL is false, this function
181    merely calls the basic initialization of the module and does not do
182    anything more.  Doing this is not really required but when running
183    in a threaded environment we might get a race condition
184    otherwise. */
185 void
186 _gcry_rngsystem_initialize (int full)
187 {
188   basic_initialization ();
189   if (!full)
190     return;
191   /* Nothing more to initialize.  */
192   return;
193 }
194
195
196 /* Try to close the FDs of the random gather module.  This is
197    currently only implemented for rndlinux. */
198 void
199 _gcry_rngsystem_close_fds (void)
200 {
201   lock_rng ();
202 #if USE_RNDLINUX
203   _gcry_rndlinux_gather_random (NULL, 0, 0, 0);
204 #endif
205   unlock_rng ();
206 }
207
208
209 /* Print some statistics about the RNG.  */
210 void
211 _gcry_rngsystem_dump_stats (void)
212 {
213   /* Not yet implemented.  */
214 }
215
216
217 /* This function returns true if no real RNG is available or the
218    quality of the RNG has been degraded for test purposes.  */
219 int
220 _gcry_rngsystem_is_faked (void)
221 {
222   return 0;  /* Faked random is not supported.  */
223 }
224
225
226 /* Add BUFLEN bytes from BUF to the internal random pool.  QUALITY
227    should be in the range of 0..100 to indicate the goodness of the
228    entropy added, or -1 for goodness not known. */
229 gcry_error_t
230 _gcry_rngsystem_add_bytes (const void *buf, size_t buflen, int quality)
231 {
232   (void)buf;
233   (void)buflen;
234   (void)quality;
235   return 0;  /* Not implemented. */
236 }
237
238
239 /* Public function to fill the buffer with LENGTH bytes of
240    cryptographically strong random bytes.  Level GCRY_WEAK_RANDOM is
241    here mapped to GCRY_STRONG_RANDOM, GCRY_STRONG_RANDOM is strong
242    enough for most usage, GCRY_VERY_STRONG_RANDOM is good for key
243    generation stuff but may be very slow.  */
244 void
245 _gcry_rngsystem_randomize (void *buffer, size_t length,
246                            enum gcry_random_level level)
247 {
248   _gcry_rngsystem_initialize (1);  /* Auto-initialize if needed.  */
249
250   if (level != GCRY_VERY_STRONG_RANDOM)
251     level = GCRY_STRONG_RANDOM;
252
253   lock_rng ();
254   get_random (buffer, length, level);
255   unlock_rng ();
256 }