entropy.c revision cc083bb7031c04d57cbad41b2f5a796a4fd1865c
/*
* Copyright (C) 2000, 2001 Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
* DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
* INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: entropy.c,v 1.69 2003/09/11 01:49:17 marka Exp $ */
/*
* This is the system depenedent part of the ISC entropy API.
*/
#include <config.h>
#include <unistd.h>
#include <isc/platform.h>
#include <isc/strerror.h>
#ifdef ISC_PLATFORM_NEEDSYSSELECTH
#endif
#include "errno2result.h"
/*
* There is only one variable in the entropy data structures that is not
* system independent, but pulling the structure that uses it into this file
* ultimately means pulling several other independent structures here also to
* resolve their interdependencies. Thus only the problem variable's type
* is defined here.
*/
#define FILESOURCE_HANDLE_TYPE int
typedef struct {
int handle;
enum {
} status;
#include "../entropy.c"
static unsigned int
unsigned char buf[128];
unsigned int added;
return (0);
added = 0;
while (desired > 0) {
if (n < 0) {
goto out;
goto err;
}
if (n == 0)
goto err;
added += n * 8;
desired -= n;
}
goto out;
err:
out:
return (added);
}
static unsigned int
unsigned char buf[128];
unsigned int added;
return (0);
added = 0;
while (desired > 0) {
errno == ECONNRESET)
goto out;
goto err;
}
INSIST(n == 1);
goto eagain_loop;
buf[0] = 1;
errno == ECONNRESET)
goto out;
goto err;
}
if (n == 1) {
goto eagain_loop;
}
INSIST(n == 2);
/*FALLTHROUGH*/
case isc_usocketsource_wrote:
/*
* The problem of EAGAIN (try again
* later) is a major issue on HP-UX.
* Solaris actually tries the recv
* call again, while HP-UX just dies.
* This code is an attempt to let the
* entropy pool fill back up (at least
* that's what I think the problem is.)
* We go to eagain_loop because if we
* just "break", then the "desired"
* amount gets borked.
*/
usleep(1000);
goto eagain_loop;
}
goto out;
goto err;
}
sz_to_recv = buf[0];
if (sz_to_recv > sizeof(buf))
goto err;
/*FALLTHROUGH*/
if (sz_to_recv != 0) {
if (n < 0) {
if (errno == EWOULDBLOCK ||
goto out;
goto err;
}
} else
n = 0;
break;
default:
goto err;
}
if ((size_t)n != sz_to_recv)
else
if (n == 0)
goto out;
added += n * 8;
desired -= n;
}
goto out;
err:
out:
return (added);
}
/*
* Poll each source, trying to get data from it to stuff into the entropy
* pool.
*/
static void
unsigned int added;
unsigned int remaining;
unsigned int needed;
unsigned int nsource;
/*
* This logic is a little strange, so an explanation is in order.
*
* If needed is 0, it means we are being asked to "fill to whatever
* we think is best." This means that if we have at least a
* partially full pool (say, > 1/4th of the pool) we probably don't
* need to add anything.
*
* Also, we will check to see if the "pseudo" count is too high.
* If it is, try to mix in better data. Too high is currently
* defined as 1/4th of the pool.
*
* Next, if we are asked to add a specific bit of entropy, make
* certain that we will do so. Clamp how much we try to add to
* (DIGEST_SIZE * 8 < needed < POOLBITS - entropy).
*
* Note that if we are in a blocking mode, we will only try to
* get as much data as we need, not as much as we might want
* to build up.
*/
if (needed == 0) {
return;
} else {
}
/*
* In any case, clamp how much we need to how much we can add.
*/
/*
* But wait! If we're not yet initialized, we need at least
* THRESHOLD_BITS
* of randomness.
*/
/*
* Poll each file source to see if we can read anything useful from
* it. XXXMLG When where are multiple sources, we should keep a
* record of which one we last used so we can start from it (or the
* next one) to avoid letting some sources build up entropy while
* others are always drained.
*/
added = 0;
return;
}
unsigned int got;
if (remaining == 0)
break;
got = 0;
case ENTROPY_SOURCETYPE_FILE:
break;
break;
}
}
int fds;
if (fds > 0)
goto again_file;
}
/*
* Here, if there are bits remaining to be had and we can block,
* check to see if we have a callback source. If so, call them.
*/
unsigned int got;
got = 0;
break;
}
/*
* Mark as initialized if we've added enough data.
*/
}
static int
int cc;
maxfd = -1;
if (fd >= 0) {
}
}
if (fd >= 0) {
break;
break;
case isc_usocketsource_wrote:
break;
}
}
}
}
if (maxfd < 0)
return (-1);
if (cc < 0)
return (-1);
return (cc);
}
static void
}
static void
}
/*
* Make a fd non-blocking
*/
static isc_result_t
make_nonblock(int fd) {
int ret;
int flags;
char strbuf[ISC_STRERRORSIZE];
flags |= O_NONBLOCK;
if (ret == -1) {
"fcntl(%d, F_SETFL, %d): %s",
return (ISC_R_UNEXPECTED);
}
return (ISC_R_SUCCESS);
}
int fd;
goto errout;
}
/*
* Solaris 2.5.1 does not have support for sockets (S_IFSOCK),
* but it does return type S_IFIFO (the OS believes that
* the socket is a fifo). This may be an issue if we tell
* the program to look at an actual FIFO as its source of
* entropy.
*/
#if defined(S_ISSOCK)
#endif
#if defined(S_ISFIFO)
#endif
if (is_usocket)
else
if (fd < 0) {
goto errout;
}
if (ret != ISC_R_SUCCESS)
goto closefd;
if (is_usocket) {
struct sockaddr_un sname;
#ifdef ISC_PLATFORM_HAVESALEN
#if !defined(SUN_LEN)
#endif
#endif
sizeof(struct sockaddr_un)) < 0) {
if (errno != EINPROGRESS) {
goto closefd;
}
} else
}
goto closefd;
}
/*
* From here down, no failures can occur.
*/
if (is_usocket) {
if (is_connected)
else
} else {
}
/*
* Hook it into the entropy system.
*/
return (ISC_R_SUCCESS);
return (ret);
}