summaryrefslogtreecommitdiff
path: root/src/fips.c
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/fips.c
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/fips.c')
-rw-r--r--src/fips.c90
1 files changed, 75 insertions, 15 deletions
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;