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