summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2007-08-23 07:29:14 +0000
committerWerner Koch <wk@gnupg.org>2007-08-23 07:29:14 +0000
commit187e9b2fda92559e2c076630328a8030fb2c3780 (patch)
treef3ea51155acde1fe25a491c3b286956f92a6c647
parentec17c36e226eae10d687d57aa0576cc38b7eebe6 (diff)
downloadlibgcrypt-187e9b2fda92559e2c076630328a8030fb2c3780.tar.gz
Use extra counter to check random pool filling.
Updated the documentation. Typo and comment fixes.
-rw-r--r--TODO29
-rw-r--r--cipher/ChangeLog5
-rw-r--r--cipher/random.c47
-rw-r--r--doc/gcrypt.texi23
-rw-r--r--src/dumpsexp.c57
5 files changed, 121 insertions, 40 deletions
diff --git a/TODO b/TODO
index 3870dd0e..6a2a3d53 100644
--- a/TODO
+++ b/TODO
@@ -26,6 +26,8 @@ What's left to do -*- outline -*-
the asymmetric ciphers could be changed for convenient interaction
with the ac interface (i.e. by using ac's `data sets') and the pk
interface could be changed to be a wrapper for the ac interface.
+ ==> It is unlikely that we will do that. The AC interafce turned
+ out to be more complicated than the regular one.
* cipher/pubkey.c and pubkey implementaions.
Don't rely on the secure memory based wiping function but add an
@@ -34,19 +36,6 @@ What's left to do -*- outline -*-
* update/improve documentation
** it's outdated for e.g. gcry_pk_algo_info.
** document algorithm capabilities
-** Explain seed files and correlation
- Multiple instances of the applications sharing the same random seed
- file can be started in parallel, in which case they will read out
- the same pool and then race for updating it (the last update
- overwrites earlier updates). They will differentiate only by the
- weak entropy that is added in read_seed_file based on the PID and
- clock, and up to 16 bytes of weak random non-blockingly. The
- consequence is that the output of these different instances is
- correlated to some extent. In the perfect scenario, the attacker
- can control (or at least guess) the PID and clock of the
- application, and drain the system's entropy pool to reduce the "up
- to 16 bytes" above to 0. Then the dependencies of the inital states
- of the pools are completely known.
** Init requirements for random
The documentation says in "Controlling the library" that some
functions can only be used at initialization time, but it does not
@@ -72,7 +61,7 @@ What's left to do -*- outline -*-
* Use builtin bit functions of gcc 3.4
-* Consider using a daemon to maintaint he random pool
+* Consider using a daemon to maintain the random pool
[Partly done] The down side of this is that we can't assume that the
random has has always been stored in "secure memory". And we rely
on that sniffing of Unix domain sockets is not possible. We can
@@ -102,18 +91,6 @@ What's left to do -*- outline -*-
* gcryptrnd.c
Requires a test for pth [done] as well as some other tests.
-* random.c
- If add_randomness is invoked before the pool is filled, but with a
- weak source of entropy, for example the fast random poll, which
- may happen from other parts of gcrypt, then the pool is filled
- partially with weak random, defeating the purpose of pool_filled
- and the "source > 1" check in add_randomness.
-
- Suggestion: Count initial filling bytes with source > 1 in
- add_randomness seperately from the pool_writepos cursor. Only set
- pool_filled if really POOLSIZE bytes with source > 1 have been
- added.
-
* secmem.c
Check whether the memory block is valid before releasing it and
print a diagnosic, like glibc does.
diff --git a/cipher/ChangeLog b/cipher/ChangeLog
index 0e9df8f0..868a8ada 100644
--- a/cipher/ChangeLog
+++ b/cipher/ChangeLog
@@ -1,3 +1,8 @@
+2007-08-23 Werner Koch <wk@g10code.com>
+
+ * random.c (pool_filled_counter): New.
+ (add_randomness): Use it.
+
2007-08-22 Werner Koch <wk@g10code.com>
* rndw32.c, rndunix.c: Switched to LGPL.
diff --git a/cipher/random.c b/cipher/random.c
index 5c8aee98..40a4219a 100644
--- a/cipher/random.c
+++ b/cipher/random.c
@@ -112,10 +112,14 @@ static size_t pool_writepos;
static size_t pool_readpos;
/* This flag is set to true as soon as the pool has been completely
- filles. This may happen either by rerading a seed file or by
- adding enough entropy. */
+ filled the first time. This may happen either by rereading a seed
+ file or by adding enough entropy. */
static int pool_filled;
+/* This counter is used to track whether the initial seeding has been
+ done with enough bytes from a reliable entropy source. */
+static size_t pool_filled_counter;
+
/* If random of level GCRY_VERY_STRONG_RANDOM has been requested we
have stricter requirements on what kind of entropy is in the pool.
In particular POOL_FILLED is not sufficient. Thus we add some
@@ -133,7 +137,7 @@ static int pool_balance;
static int just_mixed;
/* The name of the seed file or NULL if no seed file has been defined.
- The seed file needs to be regsitered at initialiation time. we
+ The seed file needs to be regsitered at initialiation time. We
keep a malloced copy here. */
static char *seed_file_name;
@@ -742,8 +746,21 @@ lock_seed_file (int fd, const char *fname, int for_write)
}
-/* Read in a seed form the random_seed file
- and return true if this was successful. */
+/* Read in a seed from the random_seed file and return true if this
+ was successful.
+
+ Note: Multiple instances of applications sharing the same random
+ seed file can be started in parallel, in which case they will read
+ out the same pool and then race for updating it (the last update
+ overwrites earlier updates). They will differentiate only by the
+ weak entropy that is added in read_seed_file based on the PID and
+ clock, and up to 16 bytes of weak random non-blockingly. The
+ consequence is that the output of these different instances is
+ correlated to some extent. In the perfect scenario, the attacker
+ can control (or at least guess) the PID and clock of the
+ application, and drain the system's entropy pool to reduce the "up
+ to 16 bytes" above to 0. Then the dependencies of the inital
+ states of the pools are completely known. */
static int
read_seed_file (void)
{
@@ -837,7 +854,7 @@ read_seed_file (void)
/* And read a few bytes from our entropy source. By using a level
* of 0 this will not block and might not return anything with some
* entropy drivers, however the rndlinux driver will use
- * /dev/urandom and return some stuff - Do not read to much as we
+ * /dev/urandom and return some stuff - Do not read too much as we
* want to be friendly to the scare system entropy resource. */
read_random_source ( RANDOM_ORIGIN_INIT, 16, GCRY_WEAK_RANDOM );
@@ -927,7 +944,7 @@ _gcry_update_random_seed_file()
/* Read random out of the pool. This function is the core of the
public random functions. Note that Level GCRY_WEAK_RANDOM is not
- anymore handled special and in fact is an alias in teh API for
+ anymore handled special and in fact is an alias in the API for
level GCRY_STRONG_RANDOM. Must be called with the pool already
locked. */
static void
@@ -1059,8 +1076,8 @@ read_pool (byte *buffer, size_t length, int level)
/* We need to detect whether a fork has happened. A fork might have
an identical pool and thus the child and the parent could emit
the very same random number. This test here is to detect forks
- in a multi-threaded process. It does not work with all trhead
- implementaions in particualr not with pthreads. However it is
+ in a multi-threaded process. It does not work with all thread
+ implementations in particular not with pthreads. However it is
good enough for GNU Pth. */
if ( getpid () != my_pid2 )
{
@@ -1091,8 +1108,16 @@ add_randomness (const void *buffer, size_t length, enum random_origins origin)
rndpool[pool_writepos++] ^= *p++;
if (pool_writepos >= POOLSIZE )
{
- if (origin >= RANDOM_ORIGIN_SLOWPOLL)
- pool_filled = 1;
+ /* It is possible that we are invoked before the pool is
+ filled using an unreliable origin of entropy, for example
+ the fast random poll. To avoid flagging the pool as
+ filled in this case, we track the initial filling state
+ separately. See also the remarks about the seed file. */
+ if (origin >= RANDOM_ORIGIN_SLOWPOLL && !pool_filled)
+ {
+ if (++pool_filled_counter >= POOLSIZE)
+ pool_filled = 1;
+ }
pool_writepos = 0;
mix_pool(rndpool); rndstats.mixrnd++;
just_mixed = !length;
diff --git a/doc/gcrypt.texi b/doc/gcrypt.texi
index 4258dfd6..c475aac8 100644
--- a/doc/gcrypt.texi
+++ b/doc/gcrypt.texi
@@ -570,14 +570,29 @@ FIXME: what about initialization time?
This command specifies the file, which is to be used as seed file for
the PRNG. If the seed file is registered prior to initialization of the
PRNG, the seed file's content (if it exists and seems to be valid) is
-feed into the PRNG pool. After the seed file has been registered, the
+fed into the PRNG pool. After the seed file has been registered, the
PRNG can be signalled to write out the PRNG pool's content into the seed
file with the following command.
+
@item GCRYCTL_UPDATE_RANDOM_SEED_FILE; Arguments: none
Write out the PRNG pool's content into the registered seed file.
+Multiple instances of the applications sharing the same random seed file
+can be started in parallel, in which case they will read out the same
+pool and then race for updating it (the last update overwrites earlier
+updates). They will differentiate only by the weak entropy that is
+added in read_seed_file based on the PID and clock, and up to 16 bytes
+of weak random non-blockingly. The consequence is that the output of
+these different instances is correlated to some extent. In the perfect
+scenario, the attacker can control (or at least guess) the PID and clock
+of the application, and drain the system's entropy pool to reduce the
+"up to 16 bytes" above to 0. Then the dependencies of the inital states
+of the pools are completely known. Note that this is not an issue if
+random of @code{GCRY_VERY_STRONG_RANDOM} quality is requested as in this
+case enough extra entropy gets mixed.
+
@item GCRYCTL_SET_VERBOSITY
@@ -1241,6 +1256,12 @@ future use.
@item GCRY_CIPHER_SEED
A 128 bit cipher as described by RFC4269.
+@item GCRY_CIPHER_CAMELLIA128
+@itemx GCRY_CIPHER_CAMELLIA192
+@itemx GCRY_CIPHER_CAMELLIA256
+The Camellia cipher by NTT. See
+@uref{http://info.isl.ntt.co.jp/@/crypt/@/eng/@/camellia/@/specifications.html}.
+
@end table
@node Cipher modules
diff --git a/src/dumpsexp.c b/src/dumpsexp.c
index 6f031047..2494c187 100644
--- a/src/dumpsexp.c
+++ b/src/dumpsexp.c
@@ -32,6 +32,7 @@
static int verbose; /* Verbose mode. */
static int decimal; /* Print addresses in decimal. */
+static int assume_hex; /* Assume input is hexencoded. */
static void
print_version (int with_help)
@@ -49,6 +50,8 @@ print_version (int with_help)
"Usage: " PGM " [OPTIONS] [file]\n"
"Debug tool for S-expressions\n"
"\n"
+ " --decimal Print offsetc using decimal notation\n"
+ " --assume-hex Assume input is a hex dump\n"
" --verbose Show what we are doing\n"
" --version Print version of the program and exit\n"
" --help Display this help and exit\n"
@@ -66,13 +69,16 @@ print_usage (void)
}
-#define digit_p(a) ((a) >= '0' && (a) <= '9')
+#define space_p(a) ((a)==' ' || (a)=='\n' || (a)=='\r' || (a)=='\t')
+#define digit_p(a) ((a) >= '0' && (a) <= '9')
#define octdigit_p(a) ((a) >= '0' && (a) <= '7')
#define alpha_p(a) ( ((a) >= 'A' && (a) <= 'Z') \
|| ((a) >= 'a' && (a) <= 'z'))
#define hexdigit_p(a) (digit_p (a) \
|| ((a) >= 'A' && (a) <= 'F') \
|| ((a) >= 'a' && (a) <= 'f'))
+#define xtoi_1(a) ((a) <= '9'? ((a)- '0'): \
+ (a) <= 'F'? ((a)-'A'+10):((a)-'a'+10))
/* Return true if P points to a byte containing a whitespace according
@@ -109,6 +115,46 @@ static int nbytesprinted;
/* The file offset of the current data buffer . */
static unsigned long databufferoffset;
+
+
+static int
+my_getc (FILE *fp)
+{
+ int c1, c2;
+
+ if (!assume_hex)
+ return getc (fp);
+
+ while ( (c1=getc (fp)) != EOF && space_p (c1) )
+ ;
+ if (c1 == EOF)
+ return EOF;
+
+ if (!hexdigit_p (c1))
+ {
+ logit ("non hex-digit encountered\n");
+ return EOF;
+ }
+
+ while ( (c2=getc (fp)) != EOF && space_p (c2) )
+ ;
+ if (c2 == EOF)
+ {
+ logit ("error reading second hex nibble\n");
+ return EOF;
+ }
+ if (!hexdigit_p (c2))
+ {
+ logit ("second hex nibble is not a hex-digit\n");
+ return EOF;
+ }
+ return xtoi_1 (c1) * 16 + xtoi_1 (c2);
+}
+
+
+
+
+
/* Flush the raw data buffer. */
static void
flushdatabuffer (void)
@@ -229,6 +275,8 @@ printhex (int c)
+
+
static int
parse_and_print (FILE *fp)
{
@@ -253,7 +301,7 @@ parse_and_print (FILE *fp)
state = INIT_STATE;
- while ((c = getc (fp)) != EOF )
+ while ((c = my_getc (fp)) != EOF )
{
addrawdata (c);
switch (state)
@@ -527,6 +575,11 @@ main (int argc, char **argv)
argc--; argv++;
decimal = 1;
}
+ else if (!strcmp (*argv, "--assume-hex"))
+ {
+ argc--; argv++;
+ assume_hex = 1;
+ }
else
print_usage ();
}