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