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/fips.c | |
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/fips.c')
-rw-r--r-- | src/fips.c | 90 |
1 files changed, 75 insertions, 15 deletions
@@ -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; |