summaryrefslogtreecommitdiffabout
path: root/pwmanager/libcrypt/cipher/rndegd.c
Unidiff
Diffstat (limited to 'pwmanager/libcrypt/cipher/rndegd.c') (more/less context) (ignore whitespace changes)
-rw-r--r--pwmanager/libcrypt/cipher/rndegd.c256
1 files changed, 256 insertions, 0 deletions
diff --git a/pwmanager/libcrypt/cipher/rndegd.c b/pwmanager/libcrypt/cipher/rndegd.c
new file mode 100644
index 0000000..29b48e8
--- a/dev/null
+++ b/pwmanager/libcrypt/cipher/rndegd.c
@@ -0,0 +1,256 @@
1 /* rndegd.c -interface to the EGD
2 *Copyright (C) 1999, 2000, 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#include <config.h>
22#include <stdio.h>
23#include <stdlib.h>
24#include <assert.h>
25#include <errno.h>
26#include <sys/time.h>
27#include <sys/stat.h>
28#include <string.h>
29#include <unistd.h>
30#include <sys/types.h>
31#include <sys/socket.h>
32#include <sys/un.h>
33#include "types.h"
34#include "g10lib.h"
35#include "cipher.h"
36#include "rand-internal.h"
37
38#ifndef offsetof
39#define offsetof(type, member) ((size_t) &((type *)0)->member)
40#endif
41
42static int egd_socket = -1;
43
44/* Allocate a new filename from FIRST_PART and SECOND_PART and to
45 tilde expansion for first_part. SECOND_PART might be NULL.
46 */
47static char *
48my_make_filename (const char *first_part, const char *second_part)
49{
50 size_t n;
51 char *name, *home, *p;
52
53 n = strlen(first_part)+1;
54 if (second_part)
55 n += strlen (second_part) + 1;
56
57 home = NULL;
58 if( *first_part == '~' && first_part[1] == '/'
59 && (home = getenv("HOME")) && *home )
60 n += strlen(home);
61
62 name = gcry_xmalloc(n);
63 p = (home
64 ? stpcpy (stpcpy (name, home), first_part+1 )
65 : stpcpy (name, first_part) );
66
67 if (second_part)
68 strcpy (stpcpy(p,"/"), second_part);
69
70 return name;
71}
72
73
74static int
75do_write( int fd, void *buf, size_t nbytes )
76{
77 size_t nleft = nbytes;
78 int nwritten;
79
80 while( nleft > 0 )
81 {
82 nwritten = write( fd, buf, nleft);
83 if( nwritten < 0 )
84 {
85 if( errno == EINTR )
86 continue;
87 return -1;
88 }
89 nleft -= nwritten;
90 buf = (char*)buf + nwritten;
91 }
92 return 0;
93}
94
95static int
96do_read( int fd, void *buf, size_t nbytes )
97{
98 int n, nread = 0;
99
100 do
101 {
102 do
103 {
104 n = read(fd, (char*)buf + nread, nbytes );
105 }
106 while( n == -1 && errno == EINTR );
107 if( n == -1)
108 return nread? nread:-1;
109 if( n == 0)
110 return -1;
111 nread += n;
112 nbytes -= n;
113 }
114 while( nread < nbytes );
115 return nread;
116}
117
118
119/* Connect to the EGD and return the file descriptor. Return -1 on
120 error. With NOFAIL set to true, silently fail and return the
121 error, otherwise print an error message and die. */
122int
123_gcry_rndegd_connect_socket (int nofail)
124{
125 int fd;
126 const char *bname = NULL;
127 char *name;
128 struct sockaddr_un addr;
129 int addr_len;
130
131 if (egd_socket != -1)
132 {
133 close (egd_socket);
134 egd_socket = -1;
135 }
136
137#ifdef EGD_SOCKET_NAME
138 bname = EGD_SOCKET_NAME;
139#endif
140 if ( !bname || !*bname )
141 name = my_make_filename ("~/.gnupg", "entropy");
142 else
143 name = my_make_filename (bname, NULL);
144
145 if (strlen(name)+1 >= sizeof addr.sun_path)
146 log_fatal ("EGD socketname is too long\n");
147
148 memset( &addr, 0, sizeof addr );
149 addr.sun_family = AF_UNIX;
150 strcpy( addr.sun_path, name );
151 addr_len = (offsetof( struct sockaddr_un, sun_path )
152 + strlen( addr.sun_path ));
153
154 fd = socket(AF_UNIX, SOCK_STREAM, 0);
155 if (fd == -1 && !nofail)
156 log_fatal("can't create unix domain socket: %s\n", strerror(errno) );
157 else if (connect (fd, (struct sockaddr*)&addr, addr_len) == -1)
158 {
159 if (!nofail)
160 log_fatal("can't connect to EGD socket `%s': %s\n",
161 name, strerror(errno) );
162 close (fd);
163 fd = -1;
164 }
165 gcry_free(name);
166 if (fd != -1)
167 egd_socket = fd;
168 return fd;
169}
170
171/****************
172 * Note: We always use the highest level.
173 * To boost the performance we may want to add some
174 * additional code for level 1
175 *
176 * Using a level of 0 should never block and better add nothing
177 * to the pool. So this is just a dummy for EGD.
178 */
179int
180_gcry_rndegd_gather_random (void (*add)(const void*, size_t, int),
181 int requester,
182 size_t length, int level )
183{
184 int fd = egd_socket;
185 int n;
186 byte buffer[256+2];
187 int nbytes;
188 int do_restart = 0;
189
190 if( !length )
191 return 0;
192 if( !level )
193 return 0;
194
195 restart:
196 if (fd == -1 || do_restart)
197 fd = _gcry_rndegd_connect_socket (0);
198
199 do_restart = 0;
200
201 nbytes = length < 255? length : 255;
202 /* First time we do it with a non blocking request */
203 buffer[0] = 1; /* non blocking */
204 buffer[1] = nbytes;
205 if( do_write( fd, buffer, 2 ) == -1 )
206 log_fatal("can't write to the EGD: %s\n", strerror(errno) );
207 n = do_read( fd, buffer, 1 );
208 if( n == -1 )
209 {
210 log_error("read error on EGD: %s\n", strerror(errno));
211 do_restart = 1;
212 goto restart;
213 }
214 n = buffer[0];
215 if( n )
216 {
217 n = do_read( fd, buffer, n );
218 if( n == -1 )
219 {
220 log_error("read error on EGD: %s\n", strerror(errno));
221 do_restart = 1;
222 goto restart;
223 }
224 (*add)( buffer, n, requester );
225 length -= n;
226 }
227
228 if( length )
229 {
230 log_info (
231 _("Please wait, entropy is being gathered. Do some work if it would\n"
232 "keep you from getting bored, because it will improve the quality\n"
233 "of the entropy.\n") );
234 }
235 while( length )
236 {
237 nbytes = length < 255? length : 255;
238
239 buffer[0] = 2; /* blocking */
240 buffer[1] = nbytes;
241 if( do_write( fd, buffer, 2 ) == -1 )
242 log_fatal("can't write to the EGD: %s\n", strerror(errno) );
243 n = do_read( fd, buffer, nbytes );
244 if( n == -1 )
245 {
246 log_error("read error on EGD: %s\n", strerror(errno));
247 do_restart = 1;
248 goto restart;
249 }
250 (*add)( buffer, n, requester );
251 length -= n;
252 }
253 memset(buffer, 0, sizeof(buffer) );
254
255 return 0; /* success */
256}