diff options
author | Werner Koch <wk@gnupg.org> | 2008-08-22 19:17:05 +0000 |
---|---|---|
committer | Werner Koch <wk@gnupg.org> | 2008-08-22 19:17:05 +0000 |
commit | 8773461c06ced4014ce2913b2621987c601a9ac0 (patch) | |
tree | 72d661ad427db4b6107b263a37025682c4ea4470 /src | |
parent | 393d3b3b0cb80223cde9be75a6a10169e37c5778 (diff) | |
download | libgcrypt-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/ChangeLog | 11 | ||||
-rw-r--r-- | src/Makefile.am | 9 | ||||
-rw-r--r-- | src/cipher-proto.h | 1 | ||||
-rw-r--r-- | src/fips.c | 90 | ||||
-rw-r--r-- | src/global.c | 7 | ||||
-rw-r--r-- | src/hmac256.c | 117 | ||||
-rw-r--r-- | src/hmac256.h | 3 |
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*/ @@ -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*/ |