~ubuntu-branches/ubuntu/oneiric/gnupg2/oneiric-updates

« back to all changes in this revision

Viewing changes to cipher/rndlinux.c

  • Committer: Bazaar Package Importer
  • Author(s): Thomas Viehmann
  • Date: 2008-10-04 10:25:53 UTC
  • mfrom: (5.1.15 intrepid)
  • Revision ID: james.westby@ubuntu.com-20081004102553-fv62pp8dsitxli47
Tags: 2.0.9-3.1
* Non-maintainer upload.
* agent/gpg-agent.c: Deinit the threading library before exec'ing
  the command to run in --daemon mode. And because that still doesn't
  restore the sigprocmask, do that manually. Closes: #499569

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* rndlinux.c  -  raw random number for OSes with /dev/random
2
 
 *      Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
3
 
 *
4
 
 * This file is part of GnuPG.
5
 
 *
6
 
 * GnuPG is free software; you can redistribute it and/or modify
7
 
 * it under the terms of the GNU General Public License as published by
8
 
 * the Free Software Foundation; either version 2 of the License, or
9
 
 * (at your option) any later version.
10
 
 *
11
 
 * GnuPG 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 General Public License for more details.
15
 
 *
16
 
 * You should have received a copy of the GNU General Public License
17
 
 * along with this program; if not, write to the Free Software
18
 
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19
 
 */
20
 
 
21
 
 
22
 
#include <config.h>
23
 
 
24
 
#ifdef USE_RNDLINUX
25
 
 
26
 
#include <stdio.h>
27
 
#include <stdlib.h>
28
 
#include <assert.h>
29
 
#include <errno.h>
30
 
#include <sys/time.h>
31
 
#include <sys/types.h>
32
 
#include <sys/stat.h>
33
 
#ifdef HAVE_GETTIMEOFDAY
34
 
  #include <sys/times.h>
35
 
#endif
36
 
#include <string.h>
37
 
#include <unistd.h>
38
 
#include <fcntl.h>
39
 
#if 0
40
 
    #include <sys/ioctl.h>
41
 
    #include <asm/types.h>
42
 
    #include <linux/random.h>
43
 
#endif
44
 
#include "types.h"
45
 
#include "util.h"
46
 
#include "ttyio.h"
47
 
#include "algorithms.h"
48
 
 
49
 
#include "i18n.h"
50
 
 
51
 
static int open_device( const char *name, int minor );
52
 
 
53
 
 
54
 
#if 0
55
 
#ifdef HAVE_DEV_RANDOM_IOCTL
56
 
static ulong
57
 
get_entropy_count( int fd )
58
 
{
59
 
    ulong count;
60
 
 
61
 
    if( ioctl( fd, RNDGETENTCNT, &count ) == -1 )
62
 
        g10_log_fatal("ioctl(RNDGETENTCNT) failed: %s\n", strerror(errno) );
63
 
    return count;
64
 
}
65
 
#endif
66
 
#endif
67
 
 
68
 
/****************
69
 
 * Used to open the /dev/random devices (Linux, xBSD, Solaris (if it exists), ...)
70
 
 */
71
 
static int
72
 
open_device( const char *name, int minor )
73
 
{
74
 
    int fd;
75
 
    struct stat sb;
76
 
 
77
 
    fd = open( name, O_RDONLY );
78
 
    if( fd == -1 )
79
 
        g10_log_fatal("can't open %s: %s\n", name, strerror(errno) );
80
 
    if( fstat( fd, &sb ) )
81
 
        g10_log_fatal("stat() off %s failed: %s\n", name, strerror(errno) );
82
 
    /* Don't check device type for better portability */
83
 
    /*  if( (!S_ISCHR(sb.st_mode)) && (!S_ISFIFO(sb.st_mode)) )
84
 
          g10_log_fatal("invalid random device!\n" ); */
85
 
    return fd;
86
 
}
87
 
 
88
 
 
89
 
/****************
90
 
 * Note:  Using a level of 0 should never block and better add nothing
91
 
 * to the pool.  This is easy to accomplish with /dev/urandom.
92
 
 */
93
 
int
94
 
rndlinux_gather_random( void (*add)(const void*, size_t, int), int requester,
95
 
                                          size_t length, int level )
96
 
{
97
 
    static int fd_urandom = -1;
98
 
    static int fd_random = -1;
99
 
    int fd;
100
 
    int n;
101
 
    int warn=0;
102
 
    byte buffer[768];
103
 
 
104
 
    if( level >= 2 ) {
105
 
        if( fd_random == -1 )
106
 
            fd_random = open_device( NAME_OF_DEV_RANDOM, 8 );
107
 
        fd = fd_random;
108
 
    }
109
 
    else {
110
 
        /* this will also be used for elve 0 but by using /dev/urandom
111
 
         * we can be sure that oit will never block. */
112
 
        if( fd_urandom == -1 )
113
 
            fd_urandom = open_device( NAME_OF_DEV_URANDOM, 9 );
114
 
        fd = fd_urandom;
115
 
    }
116
 
 
117
 
  #if 0
118
 
  #ifdef HAVE_DEV_RANDOM_IOCTL
119
 
    g10_log_info("entropy count of %d is %lu\n", fd, get_entropy_count(fd) );
120
 
  #endif
121
 
  #endif
122
 
    while( length ) {
123
 
        fd_set rfds;
124
 
        struct timeval tv;
125
 
        int rc;
126
 
 
127
 
        FD_ZERO(&rfds);
128
 
        FD_SET(fd, &rfds);
129
 
        tv.tv_sec = 3;
130
 
        tv.tv_usec = 0;
131
 
        if( !(rc=select(fd+1, &rfds, NULL, NULL, &tv)) ) {
132
 
            if( !warn )
133
 
                tty_printf(
134
 
_("\n"
135
 
"Not enough random bytes available.  Please do some other work to give\n"
136
 
"the OS a chance to collect more entropy! (Need %d more bytes)\n"), (int)length );
137
 
            warn = 1;
138
 
            continue;
139
 
        }
140
 
        else if( rc == -1 ) {
141
 
            tty_printf(
142
 
                       "select() error: %s\n", strerror(errno));
143
 
            continue;
144
 
        }
145
 
 
146
 
        do {
147
 
            int nbytes = length < sizeof(buffer)? length : sizeof(buffer);
148
 
            n = read(fd, buffer, nbytes );
149
 
            if( n >= 0 && n > nbytes ) {
150
 
                g10_log_error("bogus read from random device (n=%d)\n", n );
151
 
                n = nbytes;
152
 
            }
153
 
        } while( n == -1 && errno == EINTR );
154
 
        if( n == -1 )
155
 
            g10_log_fatal("read error on random device: %s\n", strerror(errno));
156
 
        (*add)( buffer, n, requester );
157
 
        length -= n;
158
 
    }
159
 
    memset(buffer, 0, sizeof(buffer) );
160
 
 
161
 
    return 0; /* success */
162
 
}
163
 
 
164
 
#endif /*USE_RNDLINUX*/