Bug Summary

File:lib/nettle/rnd.c
Location:line 385, column 13
Description:Called function pointer is null (null dereference)

Annotated Source Code

1/*
2 * Copyright (C) 2010, 2012 Free Software Foundation, Inc.
3 * Copyright (C) 2000, 2001, 2008 Niels Möller
4 *
5 * Author: Nikos Mavrogiannopoulos
6 *
7 * This file is part of GNUTLS.
8 *
9 * The GNUTLS library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public License
11 * as published by the Free Software Foundation; either version 3 of
12 * the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this program. If not, see <http://www.gnu.org/licenses/>
21 *
22 */
23
24/* Here is the random generator layer. This code was based on the LSH
25 * random generator (the trivia and device source functions for POSIX)
26 * and modified to fit gnutls' needs. Relicenced with permission.
27 * Original author Niels Möller.
28 */
29
30#include <gnutls_int.h>
31#include <gnutls_errors.h>
32#include <locks.h>
33#include <gnutls_num.h>
34#include <nettle/yarrow.h>
35
36#define SOURCES2 2
37
38#define RND_LOCKif (gnutls_mutex_lock(&rnd_mutex)!=0) abort() if (gnutls_mutex_lock(&rnd_mutex)!=0) abort()
39#define RND_UNLOCKif (gnutls_mutex_unlock(&rnd_mutex)!=0) abort() if (gnutls_mutex_unlock(&rnd_mutex)!=0) abort()
40
41enum
42{
43 RANDOM_SOURCE_TRIVIA = 0,
44 RANDOM_SOURCE_DEVICE,
45};
46
47static struct yarrow256_ctx yctx;
48static struct yarrow_source ysources[SOURCES2];
49static time_t device_last_read = 0;
50static time_t trivia_time_count = 0;
51
52static void *rnd_mutex;
53
54#define DEVICE_READ_INTERVAL1200 1200
55
56#ifdef _WIN32
57
58#include <windows.h>
59#include <wincrypt.h>
60
61#define DEVICE_READ_SIZE16 16
62#define DEVICE_READ_SIZE_MAX32 32
63
64static HCRYPTPROV device_fd = 0;
65
66static int
67do_trivia_source (int init)
68{
69 struct
70 {
71 FILETIME now;
72 unsigned count;
73 } event;
74
75 unsigned entropy = 0;
76
77 GetSystemTimeAsFileTime (&event.now);
78 event.count = 0;
79
80 if (init)
81 {
82 trivia_time_count = 0;
83 }
84 else
85 {
86 event.count = trivia_time_count++;
87 entropy = 1;
88 }
89
90 return yarrow256_updatenettle_yarrow256_update (&yctx, RANDOM_SOURCE_TRIVIA, entropy,
91 sizeof (event), (const uint8_t *) &event);
92}
93
94static int
95do_device_source (int init)
96{
97 time_t now = gnutls_time (NULL((void*)0));
98 int read_size = DEVICE_READ_SIZE16;
99
100 if (init)
101 {
102 int old;
103
104 if (!CryptAcquireContext
105 (&device_fd, NULL((void*)0), NULL((void*)0), PROV_RSA_FULL,
106 CRYPT_SILENT | CRYPT_VERIFYCONTEXT))
107 {
108 _gnutls_debug_log ("error in CryptAcquireContext!\n")do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log
( 2, "error in CryptAcquireContext!\n"); } while(0)
;
109 return GNUTLS_E_INTERNAL_ERROR-59;
110 }
111 device_last_read = now;
112 read_size = DEVICE_READ_SIZE_MAX32; /* initially read more data */
113 }
114
115 if ((device_fd != 0)
116 && (init || ((now - device_last_read) > DEVICE_READ_INTERVAL1200)))
117 {
118
119 /* More than 20 minutes since we last read the device */
120 uint8_t buf[DEVICE_READ_SIZE_MAX32];
121
122 if (!CryptGenRandom (device_fd, (DWORD) read_size, buf))
123 {
124 _gnutls_debug_log ("Error in CryptGenRandom: %s\n",do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log
( 2, "Error in CryptGenRandom: %s\n", GetLastError ()); } while
(0)
125 GetLastError ())do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log
( 2, "Error in CryptGenRandom: %s\n", GetLastError ()); } while
(0)
;
126 return GNUTLS_E_INTERNAL_ERROR-59;
127 }
128
129 device_last_read = now;
130 return yarrow256_updatenettle_yarrow256_update (&yctx, RANDOM_SOURCE_DEVICE,
131 read_size * 8 /
132 2 /* we trust the system RNG */ ,
133 read_size, buf);
134 }
135 return 0;
136}
137
138static void
139wrap_nettle_rnd_deinit (void *ctx)
140{
141 RND_LOCKif (gnutls_mutex_lock(&rnd_mutex)!=0) abort();
142 CryptReleaseContext (device_fd, 0);
143 RND_UNLOCKif (gnutls_mutex_unlock(&rnd_mutex)!=0) abort();
144
145 gnutls_mutex_deinit (&rnd_mutex);
146 rnd_mutex = NULL((void*)0);
147}
148
149#else /* POSIX */
150
151#include <time.h>
152#include <errno(*__errno_location ()).h>
153#include <sys/types.h>
154#include <sys/stat.h>
155#include <sys/time.h>
156#include <fcntl.h>
157#include <locks.h>
158#include <unistd.h> /* getpid */
159#ifdef HAVE_GETRUSAGE1
160#include <sys/resource.h>
161#endif
162#include "egd.h"
163
164#define DEVICE_READ_SIZE16 16
165#define DEVICE_READ_SIZE_MAX32 32
166
167static int device_fd;
168static time_t trivia_previous_time = 0;
169
170static int
171do_trivia_source (int init)
172{
173 struct
174 {
175 struct timeval now;
176#ifdef HAVE_GETRUSAGE1
177 struct rusage rusage;
178#endif
179 unsigned count;
180 pid_t pid;
181 } event;
182
183 unsigned entropy = 0;
184
185 if (gettimeofday (&event.now, NULL((void*)0)) < 0)
186 {
187 _gnutls_debug_log ("gettimeofday failed: %s\n", strerror (errno))do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log
( 2, "gettimeofday failed: %s\n", rpl_strerror ((*__errno_location
()))); } while(0)
;
188 abort ();
189 }
190#ifdef HAVE_GETRUSAGE1
191 if (getrusage (RUSAGE_SELFRUSAGE_SELF, &event.rusage) < 0)
192 {
193 _gnutls_debug_log ("getrusage failed: %s\n", strerror (errno))do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log
( 2, "getrusage failed: %s\n", rpl_strerror ((*__errno_location
()))); } while(0)
;
194 abort ();
195 }
196#endif
197
198 event.count = 0;
199 if (init)
200 {
201 trivia_time_count = 0;
202 }
203 else
204 {
205 event.count = trivia_time_count++;
206
207 if (event.now.tv_sec != trivia_previous_time)
208 {
209 /* Count one bit of entropy if we either have more than two
210 * invocations in one second, or more than two seconds
211 * between invocations. */
212 if ((trivia_time_count > 2)
213 || ((event.now.tv_sec - trivia_previous_time) > 2))
214 entropy++;
215
216 trivia_time_count = 0;
217 }
218 }
219 trivia_previous_time = event.now.tv_sec;
220 event.pid = getpid ();
221
222 return yarrow256_updatenettle_yarrow256_update (&yctx, RANDOM_SOURCE_TRIVIA, entropy,
223 sizeof (event), (const uint8_t *) &event);
224}
225
226static int
227do_device_source_urandom (int init)
228{
229 time_t now = gnutls_time (NULL((void*)0));
230 int read_size = DEVICE_READ_SIZE16;
231
232 if (init)
233 {
234 int old;
235
236 device_fd = open ("/dev/urandom", O_RDONLY00);
237 if (device_fd < 0)
238 {
239 _gnutls_debug_log ("Cannot open urandom!\n")do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log
( 2, "Cannot open urandom!\n"); } while(0)
;
240 return GNUTLS_E_FILE_ERROR-64;
241 }
242
243 old = fcntl (device_fd, F_GETFD1);
244 fcntl (device_fd, F_SETFD2, old | 1);
245 device_last_read = now;
246
247 read_size = DEVICE_READ_SIZE_MAX32; /* initially read more data */
248 }
249
250 if ((device_fd > 0)
251 && (init || ((now - device_last_read) > DEVICE_READ_INTERVAL1200)))
252 {
253 /* More than 20 minutes since we last read the device */
254 uint8_t buf[DEVICE_READ_SIZE_MAX32];
255 uint32_t done;
256
257 for (done = 0; done < read_size;)
258 {
259 int res;
260 do
261 res = read (device_fd, buf + done, sizeof (buf) - done);
262 while (res < 0 && errno(*__errno_location ()) == EINTR4);
263
264 if (res <= 0)
265 {
266 if (res < 0)
267 {
268 _gnutls_debug_log ("Failed to read /dev/urandom: %s\n",do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log
( 2, "Failed to read /dev/urandom: %s\n", rpl_strerror ((*__errno_location
()))); } while(0)
269 strerror (errno))do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log
( 2, "Failed to read /dev/urandom: %s\n", rpl_strerror ((*__errno_location
()))); } while(0)
;
270 }
271 else
272 {
273 _gnutls_debug_logdo { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log
( 2, "Failed to read /dev/urandom: end of file\n"); } while(0
)
274 ("Failed to read /dev/urandom: end of file\n")do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log
( 2, "Failed to read /dev/urandom: end of file\n"); } while(0
)
;
275 }
276
277 return GNUTLS_E_INTERNAL_ERROR-59;
278 }
279
280 done += res;
281 }
282
283 device_last_read = now;
284 return yarrow256_updatenettle_yarrow256_update (&yctx, RANDOM_SOURCE_DEVICE,
285 read_size * 8 / 2 /* we trust the RNG */ ,
286 read_size, buf);
287 }
288 return 0;
289}
290
291static int
292do_device_source_egd (int init)
293{
294 time_t now = gnutls_time (NULL((void*)0));
295 int read_size = DEVICE_READ_SIZE16;
296
297 if (init)
298 {
299 device_fd = _rndegd_connect_socket ();
300 if (device_fd < 0)
301 {
302 _gnutls_debug_log ("Cannot open egd socket!\n")do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log
( 2, "Cannot open egd socket!\n"); } while(0)
;
303 return gnutls_assert_val(GNUTLS_E_FILE_ERROR)gnutls_assert_val_int(-64, "rnd.c", 303);
304 }
305
306 device_last_read = now;
307
308 read_size = DEVICE_READ_SIZE_MAX32; /* initially read more data */
309 }
310
311 if ((device_fd > 0)
312 && (init || ((now - device_last_read) > DEVICE_READ_INTERVAL1200)))
313 {
314
315 /* More than 20 minutes since we last read the device */
316 uint8_t buf[DEVICE_READ_SIZE_MAX32];
317 uint32_t done;
318
319 for (done = 0; done < read_size;)
320 {
321 int res;
322 res = _rndegd_read (&device_fd, buf + done, sizeof (buf) - done);
323 if (res <= 0)
324 {
325 if (res < 0)
326 {
327 _gnutls_debug_log ("Failed to read egd.\n")do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log
( 2, "Failed to read egd.\n"); } while(0)
;
328 }
329 else
330 {
331 _gnutls_debug_log ("Failed to read egd: end of file\n")do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log
( 2, "Failed to read egd: end of file\n"); } while(0)
;
332 }
333
334 return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR)gnutls_assert_val_int(-59, "rnd.c", 334);
335 }
336 done += res;
337 }
338
339 device_last_read = now;
340 return yarrow256_updatenettle_yarrow256_update (&yctx, RANDOM_SOURCE_DEVICE, read_size * 8 / 2,
341 read_size, buf);
342 }
343 return 0;
344}
345
346static int
347do_device_source (int init)
348{
349 static pid_t pid; /* detect fork() */
350 int ret, reseed = 0;
351 static int (*do_source) (int init) = NULL((void*)0);
1
Variable 'do_source' initialized to a null pointer value
352/* using static var here is ok since we are
353 * always called with mutexes down
354 */
355
356 if (init == 1)
2
Taking false branch
357 {
358 pid = getpid();
359
360 do_source = do_device_source_urandom;
361 ret = do_source (init);
362 if (ret < 0)
363 {
364 do_source = do_device_source_egd;
365 ret = do_source (init);
366 }
367
368 if (ret < 0)
369 {
370 gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log
( 2, "ASSERT: %s:%d\n", "rnd.c",370); } while(0);
;
371 return ret;
372 }
373
374 return ret;
375 }
376 else
377 {
378 if (getpid() != pid)
3
Taking false branch
379 { /* fork() detected */
380 device_last_read = 0;
381 pid = getpid();
382 reseed = 1;
383 }
384
385 ret = do_source (init);
4
Called function pointer is null (null dereference)
386
387 if (reseed)
388 yarrow256_slow_reseednettle_yarrow256_slow_reseed (&yctx);
389
390 return ret;
391 }
392}
393
394
395static void
396wrap_nettle_rnd_deinit (void *ctx)
397{
398 RND_LOCKif (gnutls_mutex_lock(&rnd_mutex)!=0) abort();
399 close (device_fd);
400 RND_UNLOCKif (gnutls_mutex_unlock(&rnd_mutex)!=0) abort();
401
402 gnutls_mutex_deinit (&rnd_mutex);
403 rnd_mutex = NULL((void*)0);
404}
405
406#endif
407
408
409static int
410wrap_nettle_rnd_init (void **ctx)
411{
412 int ret;
413
414 ret = gnutls_mutex_init (&rnd_mutex);
415 if (ret < 0)
416 {
417 gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log
( 2, "ASSERT: %s:%d\n", "rnd.c",417); } while(0);
;
418 return ret;
419 }
420
421 yarrow256_initnettle_yarrow256_init (&yctx, SOURCES2, ysources);
422
423 ret = do_device_source (1);
424 if (ret < 0)
425 {
426 gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log
( 2, "ASSERT: %s:%d\n", "rnd.c",426); } while(0);
;
427 return ret;
428 }
429
430 ret = do_trivia_source (1);
431 if (ret < 0)
432 {
433 gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log
( 2, "ASSERT: %s:%d\n", "rnd.c",433); } while(0);
;
434 return ret;
435 }
436
437 yarrow256_slow_reseednettle_yarrow256_slow_reseed (&yctx);
438
439 return 0;
440}
441
442
443static int
444wrap_nettle_rnd (void *_ctx, int level, void *data, size_t datasize)
445{
446 int ret;
447
448 RND_LOCKif (gnutls_mutex_lock(&rnd_mutex)!=0) abort();
449
450 if (level != GNUTLS_RND_NONCE)
451 {
452 ret = do_trivia_source (0);
453 if (ret < 0)
454 {
455 RND_UNLOCKif (gnutls_mutex_unlock(&rnd_mutex)!=0) abort();
456 gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log
( 2, "ASSERT: %s:%d\n", "rnd.c",456); } while(0);
;
457 return ret;
458 }
459
460 ret = do_device_source (0);
461 if (ret < 0)
462 {
463 RND_UNLOCKif (gnutls_mutex_unlock(&rnd_mutex)!=0) abort();
464 gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log
( 2, "ASSERT: %s:%d\n", "rnd.c",464); } while(0);
;
465 return ret;
466 }
467 }
468
469 yarrow256_randomnettle_yarrow256_random (&yctx, datasize, data);
470 RND_UNLOCKif (gnutls_mutex_unlock(&rnd_mutex)!=0) abort();
471 return 0;
472}
473
474int crypto_rnd_prio = INT_MAX2147483647;
475
476gnutls_crypto_rnd_st _gnutls_rnd_ops = {
477 .init = wrap_nettle_rnd_init,
478 .deinit = wrap_nettle_rnd_deinit,
479 .rnd = wrap_nettle_rnd,
480};