~ubuntu-branches/ubuntu/feisty/gnupg2/feisty

« back to all changes in this revision

Viewing changes to cipher/rand-unix.c

  • Committer: Bazaar Package Importer
  • Author(s): Jonathan Riddell
  • Date: 2006-07-11 11:38:13 UTC
  • mfrom: (1.1.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20060711113813-zaw7unlbuh7gyxtl
Tags: 1.9.21-0ubuntu1
New upstream release

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* rand-unix.c  -  raw random number generator for unix like OSes
2
 
 *      Copyright (C) 1998 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
 
#include <stdio.h>
24
 
#include <stdlib.h>
25
 
#include <assert.h>
26
 
#include <errno.h>
27
 
#include <sys/time.h>
28
 
#include <sys/types.h>
29
 
#include <sys/stat.h>
30
 
#ifdef  HAVE_GETHRTIME
31
 
  #include <sys/times.h>
32
 
#endif
33
 
#ifdef HAVE_GETTIMEOFDAY
34
 
  #include <sys/times.h>
35
 
#endif
36
 
#ifdef HAVE_GETRUSAGE
37
 
  #include <sys/resource.h>
38
 
#endif
39
 
#include <string.h>
40
 
#include <unistd.h>
41
 
#include <fcntl.h>
42
 
#include "util.h"
43
 
#include "rmd.h"
44
 
#include "ttyio.h"
45
 
#include "i18n.h"
46
 
#include "rand-internal.h"
47
 
#ifdef USE_RAND_UNIX  /* This file is only for real systems */
48
 
 
49
 
 
50
 
void
51
 
random_poll()
52
 
{
53
 
    char buf[POOLSIZE/5];
54
 
    read_random_source( buf, POOLSIZE/5, 1 ); /* read /dev/urandom */
55
 
    add_randomness( buf, POOLSIZE/5, 2);
56
 
    memset( buf, 0, POOLSIZE/5);
57
 
}
58
 
 
59
 
 
60
 
void
61
 
fast_random_poll()
62
 
{
63
 
  #if HAVE_GETHRTIME
64
 
    {   hrtime_t tv;
65
 
        tv = gethrtime();
66
 
        add_randomness( &tv, sizeof(tv), 1 );
67
 
    }
68
 
  #elif HAVE_GETTIMEOFDAY
69
 
    {   struct timeval tv;
70
 
        if( gettimeofday( &tv, NULL ) )
71
 
            BUG();
72
 
        add_randomness( &tv.tv_sec, sizeof(tv.tv_sec), 1 );
73
 
        add_randomness( &tv.tv_usec, sizeof(tv.tv_usec), 1 );
74
 
    }
75
 
  #else /* use times */
76
 
    {   struct tms buf;
77
 
        times( &buf );
78
 
        add_randomness( &buf, sizeof buf, 1 );
79
 
    }
80
 
  #endif
81
 
  #ifdef HAVE_GETRUSAGE
82
 
    {   struct rusage buf;
83
 
        if( getrusage( RUSAGE_SELF, &buf ) )
84
 
            BUG();
85
 
        add_randomness( &buf, sizeof buf, 1 );
86
 
        memset( &buf, 0, sizeof buf );
87
 
    }
88
 
  #endif
89
 
}
90
 
 
91
 
 
92
 
#ifdef HAVE_DEV_RANDOM  /* we have the /dev/random devices */
93
 
 
94
 
/****************
95
 
 * Used to open the Linux and xBSD /dev/random devices
96
 
 */
97
 
static int
98
 
open_device( const char *name, int minor )
99
 
{
100
 
    int fd;
101
 
    struct stat sb;
102
 
 
103
 
    fd = open( name, O_RDONLY );
104
 
    if( fd == -1 )
105
 
        log_fatal("can't open %s: %s\n", name, strerror(errno) );
106
 
    if( fstat( fd, &sb ) )
107
 
        log_fatal("stat() off %s failed: %s\n", name, strerror(errno) );
108
 
  #if defined(__sparc__) && defined(__linux__)
109
 
    #warning something is wrong with UltraPenguin /dev/random
110
 
  #else
111
 
    if( !S_ISCHR(sb.st_mode) )
112
 
        log_fatal("invalid random device!\n" );
113
 
  #endif
114
 
    return fd;
115
 
}
116
 
 
117
 
 
118
 
void
119
 
read_random_source( byte *buffer, size_t length, int level )
120
 
{
121
 
    static int fd_urandom = -1;
122
 
    static int fd_random = -1;
123
 
    int fd;
124
 
    int n;
125
 
    int warn=0;
126
 
 
127
 
    if( level >= 2 ) {
128
 
        if( fd_random == -1 )
129
 
            fd_random = open_device( NAME_OF_DEV_RANDOM, 8 );
130
 
        fd = fd_random;
131
 
    }
132
 
    else {
133
 
        if( fd_urandom == -1 )
134
 
            fd_urandom = open_device( NAME_OF_DEV_URANDOM, 9 );
135
 
        fd = fd_urandom;
136
 
    }
137
 
    do {
138
 
        fd_set rfds;
139
 
        struct timeval tv;
140
 
        int rc;
141
 
 
142
 
        FD_ZERO(&rfds);
143
 
        FD_SET(fd, &rfds);
144
 
        tv.tv_sec = 3;
145
 
        tv.tv_usec = 0;
146
 
        if( !(rc=select(fd+1, &rfds, NULL, NULL, &tv)) ) {
147
 
            if( !warn )
148
 
                tty_printf( _(
149
 
"\n"
150
 
"Not enough random bytes available.  Please do some other work to give\n"
151
 
"the OS a chance to collect more entropy! (Need %d more bytes)\n"), length );
152
 
            warn = 1;
153
 
            continue;
154
 
        }
155
 
        else if( rc == -1 ) {
156
 
            tty_printf("select() error: %s\n", strerror(errno));
157
 
            continue;
158
 
        }
159
 
 
160
 
        do {
161
 
            n = read(fd, buffer, length );
162
 
            if( n >= 0 && n > length ) {
163
 
                log_error("bogus read from random device (n=%d)\n", n );
164
 
                n = length;
165
 
            }
166
 
        } while( n == -1 && errno == EINTR );
167
 
        if( n == -1 )
168
 
            log_fatal("read error on random device: %s\n", strerror(errno) );
169
 
        assert( n <= length );
170
 
        buffer += n;
171
 
        length -= n;
172
 
    } while( length );
173
 
}
174
 
 
175
 
#else /* not HAVE_DEV_RANDOM */
176
 
 
177
 
 
178
 
/****************
179
 
 * The real random data collector for Unix.
180
 
 * this function runs in a loop, waiting for commands from ctrl_fd
181
 
 * and normally starts a collection process, which outputs random
182
 
 * bytes to out_fd.
183
 
 *
184
 
 * Commands understand from ctrl_fd are single character:
185
 
 *  'Q' = Quit the loop
186
 
 *  'S' = Start a new collection process
187
 
 */
188
 
static void
189
 
collector( FILE *ctrlfp, FILE *outfp )
190
 
{
191
 
 
192
 
 
193
 
 
194
 
}
195
 
 
196
 
#endif /* no HAVE_DEV_RANDOM */
197
 
#endif /* USE_RAND_UNIX */