mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-29 21:47:59 +00:00
add blocking mode, and add a flag to indicate the input is a device
This commit is contained in:
parent
4979d89e04
commit
79fdce6aff
@ -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;
|
||||
|
@ -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
|
||||
|
@ -52,8 +52,8 @@
|
||||
/*
|
||||
* size of entropy pool in 32-bit words. This _MUST_ be a power of 2.
|
||||
*/
|
||||
#define RND_POOLWORDS 128
|
||||
#define RND_POOLBITS (RND_POOLWORDS * 32)
|
||||
#define RND_POOLWORDS 512
|
||||
#define RND_POOLBITS (RND_POOLWORDS * 32)
|
||||
|
||||
/*
|
||||
* Number of bytes returned per hash. This must be true:
|
||||
@ -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,11 +505,16 @@ 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 {
|
||||
/*
|
||||
* If we've extracted half our pool size in bits
|
||||
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user