84
4.4.2 Using an Alternate Entropy Source
Weve discussed devrandom and devurandom as entropy sources at some length, but what about systems that dont have these services available? Many operating systems do not provide them,
including Windows. Obtaining entropy on such systems can be problematic, but luckily, there is a solution. Several third-party packages are available for various platforms that perform entropy-
gathering services. One of the more full-featured and portable solutions available is EGADS Entropy Gathering and Distribution System. Its licensed under the BSD license, which means
that its free and the source code is available. You can obtain a copy of EGADS from
http:www.securesw.comegads .
As we mentioned, there are other entropy solutions available in addition to EGADS. EGD is an entropy-gathering daemon that is written in Perl by Brian Warner and is available from
http:egd.sourceforge.net . Because it is written in Perl, it requires a Perl interpreter to be installed.
It provides a Unix domain socket interface for clients to obtain entropy. It does not support Windows at all. PRNGD is another popular entropy-gathering daemon written by Lutz Jänicke. It
provides an EGD-compatible interface for clients to obtain entropy from it; like EGD itself, Windows is not supported. Because neither EGD nor PRNGD support Windows, well concentrate
primarily on EGADS, which does support Windows. Where appropriate, we will also discuss EGD and PRNGD together, because all three use the same interface.
Before we can use EGADS to obtain entropy, we must first initialize it. This is done with a simple call to
egads_init
. Once the library is initialized, we can use the function
egads_entropy
to obtain entropy. Like devrandom on systems that make it available,
egads_entropy
will block until enough entropy is available to satisfy the request.
Example 4-11 shows how to use EGADS
to seed OpenSSLs PRNG.
Example 4-11. Seeding OpenSSLs PRNG with EGADS
int seed_prngint bytes {
int error; char buf;
prngctx_t ctx; egads_initctx, NULL, NULL, error;
if error return 0;
buf = char mallocbytes; egads_entropyctx, buf, bytes, error;
if error RAND_seedbuf, bytes;
freebuf; egads_destroyctx;
return error; }
EGADS, EGD, and PRNGD all provide a Unix domain socket that allows clients to obtain entropy. EGD defines a simple protocol for clients to communicate with that both EGADS and
PRNGD have mimicked. Many cryptographic applications, such as GnuPG and OpenSSH, provide support for obtaining entropy from a daemon using the EGD protocol. OpenSSL also
provides support for seeding its PRNG using the EGD protocol.
OpenSSL provides two functions for communicating with a server that speaks the EGD protocol. Version 0.9.7 of OpenSSL adds a third. In addition, Version 0.9.7 will attempt to automatically
85
connect to four different commonly used names for EGD sockets in the following order: varrunegd-pool
, devegd-pool, etcegd-pool, and etcentropy.
RAND_egd
attempts to connect to the specified Unix domain socket. If the connection is successful, 255 bytes of entropy will be requested from the server. The data returned will be
passed in a call to
RAND_add
to seed the PRNG.
RAND_egd
is actually a wrapper around the next function,
RAND_egd_bytes
.
int RAND_egdconst char path; RAND_egd_bytes
will attempt to connect to the specified Unix domain socket. If the connection is successful, the specified number of bytes of entropy will be requested from the server. The data
returned will be passed in a call to
RAND_add
to seed the PRNG. Both
RAND_egd
and
RAND_egd_bytes
will return the number of bytes obtained from the EGD server if theyre successful. If an error occurred connecting to the daemon, theyll both return -1.
int RAND_egd_bytesconst char path, int bytes;
Version 0.9.7 of OpenSSL adds the function
RAND_query_egd_bytes
to make a query for data from an EGD server without automatically feeding the returned data into OpenSSLs PRNG via
RAND_add
. It attempts to connect to the specified Unix domain socket and obtain the specified number of bytes. The data that is returned from the EGD server is copied into the specified buffer.
If the buffer is specified as
NULL
, the function works just like
RAND_egd_bytes
and passes the returned data to
RAND_add
to seed the PRNG. It returns the number of bytes received on success; otherwise, it returns -1 if an error occurs.
int RAND_query_egd_bytesconst char path, unsigned char buf, int bytes;
Example 4-12 demonstrates how to use the RAND functions to access an EGD socket and seed
the PRNG with the entropy that is obtained from a running entropy-gathering server, whether its EGADS, EGD, PRNGD, or another server that provides an EGD socket interface.
Example 4-12. Seeding OpenSSLs PRNG via an EGD socket
ifndef DEVRANDOM_EGD define DEVRANDOM_EGD varrunegd-pool, devegd-pool,
etcegd-pool, \ etcentropy
endif int seed_prngint bytes
{ int i;
char names[] = { DEVRANDOM_EGD, NULL }; for i = 0; names[i]; i++
if RAND_egdnames[i] = -1 RAND_egd_bytesnames[i], 255
return 1; return 0;
}
4.5 Arbitrary Precision Math