summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2008-08-22 19:17:05 +0000
committerWerner Koch <wk@gnupg.org>2008-08-22 19:17:05 +0000
commit8773461c06ced4014ce2913b2621987c601a9ac0 (patch)
tree72d661ad427db4b6107b263a37025682c4ea4470 /src
parent393d3b3b0cb80223cde9be75a6a10169e37c5778 (diff)
downloadlibgcrypt-8773461c06ced4014ce2913b2621987c601a9ac0.tar.gz
Completed the RNG implementaion switching.
Added framework for running RNG tests. Added an experimental option --enable-hmac-binary-check to configure. --This line, and those below, will be ignored-- M src/fips.c M src/cipher-proto.h M src/global.c M src/hmac256.c M src/ChangeLog M src/hmac256.h M src/Makefile.am M tests/Makefile.am M configure.ac M doc/gcrypt.texi M random/random-fips.c M random/random.c M random/rand-internal.h M random/random.h M random/ChangeLog M ChangeLog M README
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog11
-rw-r--r--src/Makefile.am9
-rw-r--r--src/cipher-proto.h1
-rw-r--r--src/fips.c90
-rw-r--r--src/global.c7
-rw-r--r--src/hmac256.c117
-rw-r--r--src/hmac256.h3
7 files changed, 213 insertions, 25 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index b811b6ed..7f54e745 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,14 @@
+2008-08-22 Werner Koch <wk@g10code.com>
+
+ * hmac256.c (_gcry_hmac256_file): New.
+ (main): New option --binary.
+ * fips.c (check_binary_integrity): New.
+ (_gcry_fips_run_selftests): Run it.
+
+ * global.c (_gcry_vcontrol) <GCRYCTL_UPDATE_RANDOM_SEED_FILE>:
+ Check for fips operational state.
+ (_gcry_vcontrol) <GCRYCTL_FAST_POLL>: Ditt.
+
2008-08-21 Werner Koch <wk@g10code.com>
* misc.c (_gcry_log_printhex): New.
diff --git a/src/Makefile.am b/src/Makefile.am
index d9a58457..bb88520d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -121,3 +121,12 @@ endif USE_RANDOM_DAEMON
install-data-local: install-def-file
uninstall-local: uninstall-def-file
+
+# FIXME: We ned to figure out how to gte the actual name (parsing
+# libgcrypt.la?) and how to create the hmac file already at link time
+# so that it can be used without first installing.
+#install-exec-hook:
+# ./hmac256 --binary "What am I, a doctor or a moonshuttle conductor?" \
+# $(DESTDIR)$(libdir)/libgcrypt.so.11.5.0 \
+# >$(DESTDIR)$(libdir)/libgcrypt.so.11.5.0.hmac
+
diff --git a/src/cipher-proto.h b/src/cipher-proto.h
index 4b826c1d..ae5492b4 100644
--- a/src/cipher-proto.h
+++ b/src/cipher-proto.h
@@ -79,5 +79,6 @@ gcry_error_t _gcry_md_selftest (int algo, selftest_report_func_t report);
gcry_error_t _gcry_pk_selftest (int algo, selftest_report_func_t report);
gcry_error_t _gcry_hmac_selftest (int algo, selftest_report_func_t report);
+gcry_error_t _gcry_random_selftest (selftest_report_func_t report);
#endif /*G10_CIPHER_PROTO_H*/
diff --git a/src/fips.c b/src/fips.c
index ed4b9fd5..8f367977 100644
--- a/src/fips.c
+++ b/src/fips.c
@@ -22,12 +22,14 @@
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
-
-/* #include <dlfcn.h> /\* FIXME: GNU only *\/ */
+#ifdef ENABLE_HMAC_BINARY_CHECK
+# include <dlfcn.h>
+#endif
#include "g10lib.h"
#include "ath.h"
#include "cipher-proto.h"
+#include "hmac256.h"
/* The states of the finite state machine used in fips mode. */
enum module_states
@@ -417,17 +419,79 @@ run_pubkey_selftests (void)
}
-/* Run self-tests for the random number generator. Return 0 on
+/* Run self-tests for the random number generator. Returns 0 on
success. */
static int
run_random_selftests (void)
{
- char buffer[8];
+ gpg_error_t err;
- /* FIXME: For now we just try to get a few bytes. */
- gcry_randomize (buffer, sizeof buffer, GCRY_STRONG_RANDOM);
+ err = _gcry_random_selftest (reporter);
+ reporter ("random", 0, NULL, err? gpg_strerror (err):NULL);
+
+ return !!err;
+}
+/* Run an integrity check on the binary. Returns 0 on success. */
+static int
+check_binary_integrity (void)
+{
+#ifdef ENABLE_HMAC_BINARY_CHECK
+ gpg_error_t err;
+ Dl_info info;
+ unsigned char digest[32];
+ int dlen;
+ char *fname = NULL;
+ const char key[] = "What am I, a doctor or a moonshuttle conductor?";
+
+ if (!dladdr ("gcry_check_version", &info))
+ err = gpg_error_from_syserror ();
+ else
+ {
+ dlen = _gcry_hmac256_file (digest, sizeof digest, info.dli_fname,
+ key, strlen (key));
+ if (dlen < 0)
+ err = gpg_error_from_syserror ();
+ else if (dlen != 32)
+ err = gpg_error (GPG_ERR_INTERNAL);
+ else
+ {
+ FILE *fp;
+
+ fname = gcry_malloc (strlen (info.dli_fname) + 5 + 1 );
+ if (!fname)
+ err = gpg_error_from_syserror ();
+ else
+ {
+ strcpy (stpcpy (fname, info.dli_fname), ".hmac");
+ fp = fopen (fname, "rb");
+ if (!fp)
+ err = gpg_error_from_syserror ();
+ else
+ {
+ char buffer[33];
+ int n;
+
+ /* We expect a file of exactly 32 bytes. Consider
+ the self-test failed if this is not the case or
+ if it does not match the just computed HMAC. */
+ if ((n=fread (buffer, 1, 33, fp)) != 32
+ || memcmp (digest, buffer, 32) )
+ err = gpg_error (GPG_ERR_SELFTEST_FAILED);
+ else
+ err = 0;
+
+ fclose (fp);
+ }
+ }
+ }
+ }
+ reporter ("binary", 0, fname, err? gpg_strerror (err):NULL);
+ gcry_free (fname);
+ return !!err;
+#else
return 0;
+#endif
}
@@ -439,15 +503,6 @@ _gcry_fips_run_selftests (void)
fips_new_state (STATE_SELFTEST);
-/* { */
-/* Dl_info info; */
-
-/* if (dladdr ("gcry_check_version", &info)) */
-/* log_info ("DL_info: fname=`%s'\n", */
-/* info.dli_fname); */
-/* } */
-
-
if (run_cipher_selftests ())
goto leave;
@@ -463,6 +518,11 @@ _gcry_fips_run_selftests (void)
if (run_random_selftests ())
goto leave;
+ /* Now check the integrity of the binary. We do this this after
+ having checked the HMAC code. */
+ if (check_binary_integrity ())
+ goto leave;
+
/* All selftests passed. */
result = STATE_OPERATIONAL;
diff --git a/src/global.c b/src/global.c
index ed4e4807..2b7f0bcc 100644
--- a/src/global.c
+++ b/src/global.c
@@ -349,7 +349,8 @@ _gcry_vcontrol (enum gcry_ctl_cmds cmd, va_list arg_ptr)
break;
case GCRYCTL_UPDATE_RANDOM_SEED_FILE:
- _gcry_update_random_seed_file ();
+ if ( fips_is_operational () )
+ _gcry_update_random_seed_file ();
break;
case GCRYCTL_SET_VERBOSITY:
@@ -405,7 +406,9 @@ _gcry_vcontrol (enum gcry_ctl_cmds cmd, va_list arg_ptr)
/* We need to do make sure that the random pool is really
initialized so that the poll function is not a NOP. */
_gcry_random_initialize (1);
- _gcry_fast_random_poll ();
+
+ if ( fips_is_operational () )
+ _gcry_fast_random_poll ();
break;
case GCRYCTL_SET_RNDEGD_SOCKET:
diff --git a/src/hmac256.c b/src/hmac256.c
index 9cfffa27..8a318af9 100644
--- a/src/hmac256.c
+++ b/src/hmac256.c
@@ -52,6 +52,9 @@
#include <string.h>
#include <assert.h>
#include <errno.h>
+#if defined(__WIN32) && defined(STANDALONE)
+# include <fcntl.h> /* We need setmode(). */
+#endif
#include "hmac256.h"
@@ -361,6 +364,7 @@ _gcry_hmac256_release (hmac256_context_t ctx)
{
if (ctx)
{
+ /* Note: We need to take care not to modify errno. */
if (ctx->use_hmac)
my_wipememory (ctx->opad, 64);
free (ctx);
@@ -441,6 +445,78 @@ _gcry_hmac256_finalize (hmac256_context_t hd, size_t *r_dlen)
}
+/* Convenience function to compute the HMAC-SHA256 of one file. The
+ user needs to provide a buffer RESULT of at least 32 bytes, he
+ needs to put the size of the buffer into RESULTSIZE and the
+ FILENAME. KEY and KEYLEN are as described for _gcry_hmac256_new.
+ On success the function returns the valid length of the result
+ buffer (which will be 32) or -1 on error. On error ERRNO is set
+ appropriate. */
+int
+_gcry_hmac256_file (void *result, size_t resultsize, const char *filename,
+ const void *key, size_t keylen)
+{
+ FILE *fp;
+ hmac256_context_t hd;
+ size_t buffer_size, nread, digestlen;
+ char *buffer;
+ const unsigned char *digest;
+
+ fp = fopen (filename, "rb");
+ if (!fp)
+ return -1;
+
+ hd = _gcry_hmac256_new (key, keylen);
+ if (!hd)
+ {
+ fclose (fp);
+ return -1;
+ }
+
+ buffer_size = 32768;
+ buffer = malloc (buffer_size);
+ if (!buffer)
+ {
+ fclose (fp);
+ _gcry_hmac256_release (hd);
+ return -1;
+ }
+
+ while ( (nread = fread (buffer, 1, buffer_size, fp)))
+ _gcry_hmac256_update (hd, buffer, nread);
+
+ free (buffer);
+
+ if (ferror (fp))
+ {
+ fclose (fp);
+ _gcry_hmac256_release (hd);
+ return -1;
+ }
+
+ fclose (fp);
+
+ digest = _gcry_hmac256_finalize (hd, &digestlen);
+ if (!digest)
+ {
+ _gcry_hmac256_release (hd);
+ return -1;
+ }
+
+ if (digestlen > resultsize)
+ {
+ _gcry_hmac256_release (hd);
+ errno = EINVAL;
+ return -1;
+ }
+ memcpy (result, digest, digestlen);
+ _gcry_hmac256_release (hd);
+
+ return digestlen;
+}
+
+
+
#ifdef STANDALONE
static int
selftest (void)
@@ -574,8 +650,12 @@ main (int argc, char **argv)
char buffer[4096];
size_t n, dlen, idx;
int use_stdin = 0;
+ int use_binary = 0;
assert (sizeof (u32) == 4);
+#ifdef __WIN32
+ setmode (fileno (stdin), O_BINARY);
+#endif
if (argc)
{
@@ -609,14 +689,23 @@ main (int argc, char **argv)
stdout);
exit (0);
}
+ else if (!strcmp (*argv, "--binary"))
+ {
+ argc--; argv++;
+ use_binary = 1;
+ }
}
if (argc < 1)
{
- fprintf (stderr, "usage: %s key [filename]\n", pgm);
+ fprintf (stderr, "usage: %s [--binary] key [filename]\n", pgm);
exit (1);
}
+#ifdef __WIN32
+ if (use_binary)
+ setmode (fileno (stdout), O_BINARY);
+#endif
key = *argv;
argc--, argv++;
@@ -664,15 +753,27 @@ main (int argc, char **argv)
pgm, strerror (errno));
exit (1);
}
- for (idx=0; idx < dlen; idx++)
- printf ("%02x", digest[idx]);
- _gcry_hmac256_release (hd);
- if (use_stdin)
+ if (use_binary)
{
- putchar ('\n');
- break;
+ if (fwrite (digest, dlen, 1, stdout) != 1)
+ {
+ fprintf (stderr, "%s: error writing output: %s\n",
+ pgm, strerror (errno));
+ exit (1);
+ }
+ }
+ else
+ {
+ for (idx=0; idx < dlen; idx++)
+ printf ("%02x", digest[idx]);
+ _gcry_hmac256_release (hd);
+ if (use_stdin)
+ {
+ putchar ('\n');
+ break;
+ }
+ printf (" %s\n", fname);
}
- printf (" %s\n", fname);
}
return 0;
diff --git a/src/hmac256.h b/src/hmac256.h
index 2f4d1ea4..df28e727 100644
--- a/src/hmac256.h
+++ b/src/hmac256.h
@@ -29,5 +29,8 @@ void _gcry_hmac256_update (hmac256_context_t hd, const void *buf, size_t len);
const void *_gcry_hmac256_finalize (hmac256_context_t hd, size_t *r_dlen);
void _gcry_hmac256_release (hmac256_context_t hd);
+int _gcry_hmac256_file (void *result, size_t resultsize, const char *filename,
+ const void *key, size_t keylen);
+
#endif /*HMAC256_H*/