2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-30 14:07:59 +00:00

add blocking mode, and add a flag to indicate the input is a device

This commit is contained in:
Michael Graff
2000-06-09 21:36:51 +00:00
parent 4979d89e04
commit 79fdce6aff
3 changed files with 112 additions and 28 deletions

View File

@@ -26,14 +26,16 @@ static void
hex_dump(char *msg, void *data, unsigned int length) {
unsigned int len;
unsigned char *base;
isc_boolean_t first = ISC_TRUE;
base = data;
printf("DUMP of %d bytes: %s\n", length, msg);
printf("DUMP of %d bytes: %s\n\t", length, msg);
for (len = 0 ; len < length ; len++) {
if (len % 16 == 0)
printf("\n");
if (len % 16 == 0 && !first)
printf("\n\t");
printf("%02x ", base[len]);
first = ISC_FALSE;
}
printf("\n");
}
@@ -69,10 +71,20 @@ main(int argc, char **argv) {
isc_entropy_stats(ent, stderr);
#if 1
devrandom = NULL;
flags = 0;
flags |= ISC_ENTROPYSOURCE_ISDEVICE;
CHECK("isc_entropy_createfilesource()",
isc_entropy_createfilesource(ent, "/dev/random",
0, &devrandom));
flags, &devrandom));
#else
devrandom = NULL;
flags = 0;
CHECK("isc_entropy_createfilesource()",
isc_entropy_createfilesource(ent, "/tmp/foo",
flags, &devrandom));
#endif
fprintf(stderr,
"Reading 32 bytes of GOOD random data only, partial OK\n");
@@ -83,18 +95,25 @@ main(int argc, char **argv) {
result = isc_entropy_getdata(ent, buffer, 32, &returned, flags);
if (result == ISC_R_NOENTROPY) {
fprintf(stderr, "No entropy.\n");
goto out;
goto any;
}
hex_dump("good data only:", buffer, returned);
any:
isc_entropy_stats(ent, stderr);
CHECK("isc_entropy_getdata()",
isc_entropy_getdata(ent, buffer, 128, NULL, 0));
hex_dump("pseudorandom data", buffer, 128);
hex_dump("entropy data", buffer, 128);
isc_entropy_stats(ent, stderr);
flags = 0;
flags |= ISC_ENTROPY_GOODONLY;
flags |= ISC_ENTROPY_BLOCKING;
result = isc_entropy_getdata(ent, buffer, sizeof buffer, &returned,
flags);
CHECK("good data only, blocking mode", result);
hex_dump("blocking mode data", buffer, sizeof buffer);
out:
{
isc_entropy_t *entcopy1 = NULL;
isc_entropy_t *entcopy2 = NULL;

View File

@@ -96,15 +96,15 @@ ISC_LANG_BEGINDECLS
* Estimate the amount of entropy contained in the sample pool.
* If this is not set, the source will be gathered and perodically
* mixed into the entropy pool, but no increment in contained entropy
* will be assumed.
* will be assumed. This flag only makes sense on sample sources.
*
* _POLLABLE
* The entropy source is pollable for more data. This is most useful
* for things like files and devices. It should not be used for
* tty/keyboard data, device timings, etc.
* _ISDEVICE
* The file named is really a device file, and blocking is possible.
* Otherwise, the file is assumed to be a finite length file, and
* any I/O error (including blocking) terminates the source.
*/
#define ISC_ENTROPYSOURCE_ESTIMATE 0x00000001U
#define ISC_ENTROPYSOURCE_POLLABLE 0x00000002U
#define ISC_ENTROPYSOURCE_ISDEVICE 0x00000002U
/***
*** Functions

View File

@@ -52,7 +52,7 @@
/*
* size of entropy pool in 32-bit words. This _MUST_ be a power of 2.
*/
#define RND_POOLWORDS 128
#define RND_POOLWORDS 512
#define RND_POOLBITS (RND_POOLWORDS * 32)
/*
@@ -130,6 +130,9 @@ entropypool_add_word(isc_entropypool_t *, isc_uint32_t);
static void
fillpool(isc_entropy_t *, unsigned int, isc_boolean_t);
static int
wait_for_sources(isc_entropy_t *);
/*
* Add in entropy, even when the value we're adding in could be
* very large.
@@ -275,10 +278,13 @@ get_from_filesource(isc_entropysource_t *source, isc_uint32_t desired) {
int fd = source->sources.file.fd;
ssize_t n, ndesired;
isc_uint32_t added;
isc_boolean_t isdevice;
if (fd == -1)
return (0);
isdevice = ISC_TF((source->flags & ISC_ENTROPYSOURCE_ISDEVICE) != 0);
desired = desired / 8 + (((desired & 0x07) > 0) ? 1 : 0);
added = 0;
@@ -286,13 +292,17 @@ get_from_filesource(isc_entropysource_t *source, isc_uint32_t desired) {
ndesired = ISC_MIN(desired, sizeof(buf));
n = read(fd, buf, ndesired);
if (n < 0) {
if (errno == EAGAIN)
if (isdevice && (errno == EAGAIN))
goto out;
close(fd);
source->sources.file.fd = -1;
}
if (n == 0)
goto out;
}
if (n == 0) {
close(fd);
source->sources.file.fd = -1;
goto out;
}
entropypool_adddata(ent, buf, n, n * 8);
added += n * 8;
@@ -329,6 +339,10 @@ fillpool(isc_entropy_t *ent, unsigned int needed, isc_boolean_t blocking) {
* 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) {
isc_uint32_t needed_ent, needed_ps;
@@ -350,6 +364,11 @@ fillpool(isc_entropy_t *ent, unsigned int needed, isc_boolean_t blocking) {
needed = ISC_MIN(needed, RND_POOLBITS);
}
/*
* In any case, clamp how much we need to how much we can add.
*/
needed = ISC_MIN(needed, RND_POOLBITS - ent->pool.entropy);
/*
* Poll each file source to see if we can read anything useful from
* it. XXXMLG When where are multiple sources, we should keep a
@@ -358,25 +377,67 @@ fillpool(isc_entropy_t *ent, unsigned int needed, isc_boolean_t blocking) {
* others are always drained.
*/
again:
source = ISC_LIST_HEAD(ent->sources);
added = 0;
while (source != NULL) {
desired = ISC_MIN(needed, RND_POOLBITS - ent->pool.entropy);
while (source != NULL && needed > 0) {
if (source->type == ENTROPY_SOURCETYPE_FILE)
added += get_from_filesource(source, desired);
added += get_from_filesource(source, needed);
if (added > needed)
if (added >= needed)
break;
if (needed > added)
needed -= added;
else
needed = 0;
source = ISC_LIST_NEXT(source, link);
}
if (blocking && added < needed) {
if (wait_for_sources(ent) > 0)
goto again;
}
/*
* Adjust counts.
*/
subtract_pseudo(ent, added);
}
static int
wait_for_sources(isc_entropy_t *ent) {
isc_entropysource_t *source;
int maxfd, fd;
int cc;
fd_set reads;
maxfd = -1;
FD_ZERO(&reads);
source = ISC_LIST_HEAD(ent->sources);
while (source != NULL) {
if (source->type == ENTROPY_SOURCETYPE_FILE) {
fd = source->sources.file.fd;
if (fd >= 0) {
maxfd = ISC_MAX(maxfd, fd);
FD_SET(fd, &reads);
}
}
source = ISC_LIST_NEXT(source, link);
}
if (maxfd < 0)
return (-1);
cc = select(maxfd + 1, &reads, NULL, NULL, NULL);
if (cc < 0)
return (-1);
return (cc);
}
/*
* Extract some number of bytes from the random pool, decreasing the
* estimate of randomness as each byte is extracted.
@@ -444,10 +505,15 @@ isc_entropy_getdata(isc_entropy_t *ent, void *data, unsigned int length,
* are not ok.
*/
if (goodonly) {
fillpool(ent, (length - remain) * 8, blocking);
if (!partial && !blocking
fillpool(ent, remain * 8, blocking);
if (!blocking && !partial
&& ((ent->pool.entropy < count * 8)
|| (ent->pool.entropy < RND_ENTROPY_THRESHOLD * 8)))
|| (ent->pool.entropy
< RND_ENTROPY_THRESHOLD * 8)))
goto zeroize;
if (blocking
&& (ent->pool.entropy
<= RND_ENTROPY_THRESHOLD * 8))
goto zeroize;
} else {
/*
@@ -477,10 +543,9 @@ isc_entropy_getdata(isc_entropy_t *ent, void *data, unsigned int length,
deltae = ISC_MIN(deltae, ent->pool.entropy);
total += deltae;
subtract_entropy(ent, deltae);
add_pseudo(ent, count * 8);
}
add_pseudo(ent, total);
memset(digest, 0, sizeof(digest));
if (returned != NULL)