8ea4df285bf7a212f4e5af7e52f935ef33763dff
[libgcrypt.git] / random / random-daemon.c
1 /* random-daemon.c  - Access to the external random daemon
2  * Copyright (C) 2006  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    The functions here are used by random.c to divert calls to an
23    external random number daemon.  The actual daemon we use is
24    gcryptrnd.  Such a daemon is useful to keep a persistent pool in
25    memory over invocations of a single application and to allow
26    prioritizing access to the actual entropy sources.  The drawback is
27    that we need to use IPC (i.e. unix domain socket) to convey
28    sensitive data.
29  */
30
31 #include <config.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <assert.h>
35 #include <string.h>
36 #include <sys/socket.h>
37 #include <sys/un.h>
38 #include <errno.h>
39 #include <unistd.h>
40
41 #include "g10lib.h"
42 #include "random.h"
43
44 \f
45
46 /* This is default socket name we use in case the provided socket name
47    is NULL.  */
48 #define RANDOM_DAEMON_SOCKET "/var/run/libgcrypt/S.gcryptrnd"
49
50 /* The lock serializing access to the daemon.  */
51 GPGRT_LOCK_DEFINE (daemon_lock);
52
53 /* The socket connected to the daemon.  */
54 static int daemon_socket = -1;
55
56 /* Creates a socket connected to the daemon.  On success, store the
57    socket fd in *SOCK.  Returns error code.  */
58 static gcry_error_t
59 connect_to_socket (const char *socketname, int *sock)
60 {
61   struct sockaddr_un *srvr_addr;
62   socklen_t addrlen;
63   gcry_error_t err;
64   int fd;
65   int rc;
66
67   srvr_addr = NULL;
68
69   /* Create a socket. */
70   fd = socket (AF_UNIX, SOCK_STREAM, 0);
71   if (fd == -1)
72     {
73       log_error ("can't create socket: %s\n", strerror (errno));
74       err = gcry_error_from_errno (errno);
75       goto out;
76     }
77
78   /* Set up address.  */
79   srvr_addr = gcry_malloc (sizeof *srvr_addr);
80   if (! srvr_addr)
81     {
82       log_error ("malloc failed: %s\n", strerror (errno));
83       err = gcry_error_from_errno (errno);
84       goto out;
85     }
86   memset (srvr_addr, 0, sizeof *srvr_addr);
87   srvr_addr->sun_family = AF_UNIX;
88   if (strlen (socketname) + 1 >= sizeof (srvr_addr->sun_path))
89     {
90       log_error ("socket name `%s' too long\n", socketname);
91       err = gcry_error (GPG_ERR_ENAMETOOLONG);
92       goto out;
93     }
94   strcpy (srvr_addr->sun_path, socketname);
95   addrlen = (offsetof (struct sockaddr_un, sun_path)
96              + strlen (srvr_addr->sun_path) + 1);
97
98   /* Connect socket.  */
99   rc = connect (fd, (struct sockaddr *) srvr_addr, addrlen);
100   if (rc == -1)
101     {
102       log_error ("error connecting socket `%s': %s\n",
103                  srvr_addr->sun_path, strerror (errno));
104       err = gcry_error_from_errno (errno);
105       goto out;
106     }
107
108   err = 0;
109
110  out:
111
112   gcry_free (srvr_addr);
113   if (err)
114     {
115       close (fd);
116       fd = -1;
117     }
118   *sock = fd;
119
120   return err;
121 }
122
123
124 /* Initialize basics of this module. This should be viewed as a
125    constructor to prepare locking. */
126 void
127 _gcry_daemon_initialize_basics (void)
128 {
129   /* Not anymore required.  */
130 }
131
132
133
134 /* Send LENGTH bytes of BUFFER to file descriptor FD.  Returns 0 on
135    success or another value on write error. */
136 static int
137 writen (int fd, const void *buffer, size_t length)
138 {
139   ssize_t n;
140
141   while (length)
142     {
143       do
144         n = ath_write (fd, buffer, length);
145       while (n < 0 && errno == EINTR);
146       if (n < 0)
147          {
148            log_error ("write error: %s\n", strerror (errno));
149            return -1; /* write error */
150          }
151       length -= n;
152       buffer = (const char*)buffer + n;
153     }
154   return 0;  /* Okay */
155 }
156
157 static int
158 readn (int fd, void *buf, size_t buflen, size_t *ret_nread)
159 {
160   size_t nleft = buflen;
161   int nread;
162   char *p;
163
164   p = buf;
165   while (nleft > 0)
166     {
167       nread = ath_read (fd, buf, nleft);
168       if (nread < 0)
169         {
170           if (nread == EINTR)
171             nread = 0;
172           else
173             return -1;
174         }
175       else if (!nread)
176         break; /* EOF */
177       nleft -= nread;
178       buf = (char*)buf + nread;
179     }
180   if (ret_nread)
181     *ret_nread = buflen - nleft;
182   return 0;
183 }
184
185 /* This functions requests REQ_NBYTES from the daemon.  If NONCE is
186    true, the data should be suited for a nonce.  If NONCE is FALSE,
187    data of random level LEVEL will be generated.  The retrieved random
188    data will be stored in BUFFER.  Returns error code.  */
189 static gcry_error_t
190 call_daemon (const char *socketname,
191              void *buffer, size_t req_nbytes, int nonce,
192              enum gcry_random_level level)
193 {
194   static int initialized;
195   unsigned char buf[255];
196   gcry_error_t err = 0;
197   size_t nbytes;
198   size_t nread;
199   int rc;
200
201   if (!req_nbytes)
202     return 0;
203
204   gpgrt_lock_lock (&daemon_lock);
205
206   /* Open the socket if that has not been done. */
207   if (!initialized)
208     {
209       initialized = 1;
210       err = connect_to_socket (socketname ? socketname : RANDOM_DAEMON_SOCKET,
211                                &daemon_socket);
212       if (err)
213         {
214           daemon_socket = -1;
215           log_info ("not using random daemon\n");
216           gpgrt_lock_unlock (&daemon_lock);
217           return err;
218         }
219     }
220
221   /* Check that we have a valid socket descriptor. */
222   if ( daemon_socket == -1 )
223     {
224       gpgrt_lock_unlock (&daemon_lock);
225       return gcry_error (GPG_ERR_INTERNAL);
226     }
227
228
229   /* Do the real work.  */
230
231   do
232     {
233       /* Process in chunks.  */
234       nbytes = req_nbytes > sizeof (buf) ? sizeof (buf) : req_nbytes;
235       req_nbytes -= nbytes;
236
237       /* Construct request.  */
238       buf[0] = 3;
239       if (nonce)
240         buf[1] = 10;
241       else if (level == GCRY_VERY_STRONG_RANDOM)
242         buf[1] = 12;
243       else if (level == GCRY_STRONG_RANDOM)
244         buf[1] = 11;
245       buf[2] = nbytes;
246
247       /* Send request.  */
248       rc = writen (daemon_socket, buf, 3);
249       if (rc == -1)
250         {
251           err = gcry_error_from_errno (errno);
252           break;
253         }
254
255       /* Retrieve response.  */
256
257       rc = readn (daemon_socket, buf, 2, &nread);
258       if (rc == -1)
259         {
260           err = gcry_error_from_errno (errno);
261           log_error ("read error: %s\n", _gcry_strerror (err));
262           break;
263         }
264       if (nread && buf[0])
265         {
266           log_error ("random daemon returned error code %d\n", buf[0]);
267           err = gcry_error (GPG_ERR_INTERNAL); /* ? */
268           break;
269         }
270       if (nread != 2)
271         {
272           log_error ("response too small\n");
273           err = gcry_error (GPG_ERR_PROTOCOL_VIOLATION); /* ? */
274           break;
275         }
276
277       /*      if (1)*/                  /* Do this in verbose mode? */
278       /*        log_info ("received response with %d bytes of data\n", buf[1]);*/
279
280       if (buf[1] < nbytes)
281         {
282           log_error ("error: server returned less bytes than requested\n");
283           err = gcry_error (GPG_ERR_PROTOCOL_VIOLATION); /* ? */
284           break;
285         }
286       else if (buf[1] > nbytes)
287         {
288           log_error ("warning: server returned more bytes than requested\n");
289           err = gcry_error (GPG_ERR_PROTOCOL_VIOLATION); /* ? */
290           break;
291         }
292
293       assert (nbytes <= sizeof (buf));
294
295       rc = readn (daemon_socket, buf, nbytes, &nread);
296       if (rc == -1)
297         {
298           err = gcry_error_from_errno (errno);
299           log_error ("read error: %s\n", _gcry_strerror (err));
300           break;
301         }
302
303       if (nread != nbytes)
304         {
305           log_error ("too little random data read\n");
306           err = gcry_error (GPG_ERR_INTERNAL);
307           break;
308         }
309
310       /* Successfuly read another chunk of data.  */
311       memcpy (buffer, buf, nbytes);
312       buffer = ((char *) buffer) + nbytes;
313     }
314   while (req_nbytes);
315
316   gpgrt_lock_unlock (&daemon_lock);
317
318   return err;
319 }
320
321 /* Internal function to fill BUFFER with LENGTH bytes of random.  We
322    support GCRY_STRONG_RANDOM and GCRY_VERY_STRONG_RANDOM here.
323    Return 0 on success. */
324 int
325 _gcry_daemon_randomize (const char *socketname,
326                         void *buffer, size_t length,
327                         enum gcry_random_level level)
328 {
329   gcry_error_t err;
330
331   err = call_daemon (socketname, buffer, length, 0, level);
332
333   return err ? -1 : 0;
334 }
335
336 /* END */