summaryrefslogtreecommitdiffabout
path: root/pwmanager/libcrypt/cipher/rndlinux.c
Unidiff
Diffstat (limited to 'pwmanager/libcrypt/cipher/rndlinux.c') (more/less context) (show whitespace changes)
-rw-r--r--pwmanager/libcrypt/cipher/rndlinux.c141
1 files changed, 141 insertions, 0 deletions
diff --git a/pwmanager/libcrypt/cipher/rndlinux.c b/pwmanager/libcrypt/cipher/rndlinux.c
new file mode 100644
index 0000000..fc608bc
--- a/dev/null
+++ b/pwmanager/libcrypt/cipher/rndlinux.c
@@ -0,0 +1,141 @@
1/* rndlinux.c - raw random number for OSes with /dev/random
2 * Copyright (C) 1998, 2001, 2002, 2003 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, 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_GETTIMEOFDAY
31# include <sys/times.h>
32#endif
33#include <string.h>
34#include <unistd.h>
35#include <fcntl.h>
36#include "types.h"
37#include "g10lib.h"
38#include "rand-internal.h"
39
40static int open_device( const char *name, int minor );
41int _gcry_rndlinux_gather_random (void (*add)(const void*, size_t, int),
42 int requester,
43 size_t length, int level );
44
45/*
46 * Used to open the /dev/random devices (Linux, xBSD, Solaris (if it exists)).
47 */
48static int
49open_device( const char *name, int minor )
50{
51 int fd;
52
53 fd = open( name, O_RDONLY );
54 if( fd == -1 )
55 log_fatal ("can't open %s: %s\n", name, strerror(errno) );
56
57 /* We used to do the follwing check, however it turned out that this
58 is not portable since more OSes provide a random device which is
59 sometimes implemented as anoteher device type.
60
61 struct stat sb;
62
63 if( fstat( fd, &sb ) )
64 log_fatal("stat() off %s failed: %s\n", name, strerror(errno) );
65 if( (!S_ISCHR(sb.st_mode)) && (!S_ISFIFO(sb.st_mode)) )
66 log_fatal("invalid random device!\n" );
67 */
68 return fd;
69}
70
71
72int
73_gcry_rndlinux_gather_random (void (*add)(const void*, size_t, int),
74 int requester,
75 size_t length, int level )
76{
77 static int fd_urandom = -1;
78 static int fd_random = -1;
79 int fd;
80 int n;
81 int warn=0;
82 byte buffer[768];
83
84 if( level >= 2 )
85 {
86 if( fd_random == -1 )
87 fd_random = open_device( NAME_OF_DEV_RANDOM, 8 );
88 fd = fd_random;
89 }
90 else
91 {
92 if( fd_urandom == -1 )
93 fd_urandom = open_device( NAME_OF_DEV_URANDOM, 9 );
94 fd = fd_urandom;
95 }
96
97 while (length)
98 {
99 fd_set rfds;
100 struct timeval tv;
101 int rc;
102
103 FD_ZERO(&rfds);
104 FD_SET(fd, &rfds);
105 tv.tv_sec = 3;
106 tv.tv_usec = 0;
107 if( !(rc=select(fd+1, &rfds, NULL, NULL, &tv)) )
108 {
109 if( !warn )
110 {
111 _gcry_random_progress ("need_entropy", 'X', 0, (int)length);
112 warn = 1;
113 }
114 continue;
115 }
116 else if( rc == -1 )
117 {
118 log_error ("select() error: %s\n", strerror(errno));
119 continue;
120 }
121
122 do
123 {
124 int nbytes = length < sizeof(buffer)? length : sizeof(buffer);
125 n = read(fd, buffer, nbytes );
126 if( n >= 0 && n > nbytes )
127 {
128 log_error("bogus read from random device (n=%d)\n", n );
129 n = nbytes;
130 }
131 }
132 while( n == -1 && errno == EINTR );
133 if( n == -1 )
134 log_fatal("read error on random device: %s\n", strerror(errno));
135 (*add)( buffer, n, requester );
136 length -= n;
137 }
138 memset(buffer, 0, sizeof(buffer) );
139
140 return 0; /* success */
141}