Changed the HMAC binary check file format.
authorWerner Koch <wk@gnupg.org>
Thu, 11 Sep 2008 15:11:00 +0000 (15:11 +0000)
committerWerner Koch <wk@gnupg.org>
Thu, 11 Sep 2008 15:11:00 +0000 (15:11 +0000)
src/ChangeLog
src/Makefile.am
src/fips.c

index 582026b..634f440 100644 (file)
@@ -1,5 +1,9 @@
 2008-09-11  Werner Koch  <wk@g10code.com>
 
+       * fips.c: Include string.h.
+       (loxtoi_1, loxtoi_2, loxdigit_p): New.
+       (check_binary_integrity): Change the format of the expected file.
+
        * fips.c (_gcry_fips_run_selftests): Run random tests before the
        pubkey tests.
 
index dcec200..544b5e2 100644 (file)
@@ -126,7 +126,7 @@ uninstall-local: uninstall-def-file
 # libgcrypt.la?) and how to create the hmac file already at link time
 # so that it can be used without installing libgcrypt first.
 #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
+#      ./hmac256 "What am I, a doctor or a moonshuttle conductor?" \
+#          < $(DESTDIR)$(libdir)/libgcrypt.so.11.5.0 \
+#          > $(DESTDIR)$(libdir)/.libgcrypt.so.11.5.0.hmac
 
index 0402e62..d4f2fcb 100644 (file)
@@ -22,6 +22,7 @@
 #include <stdlib.h>
 #include <errno.h>
 #include <unistd.h>
+#include <string.h>
 #ifdef ENABLE_HMAC_BINARY_CHECK
 # include <dlfcn.h> 
 #endif
@@ -60,10 +61,19 @@ static enum module_states current_state;
 
 
 
+
 \f
 static void fips_new_state (enum module_states new_state);
 
 
+\f
+/* Convert lowercase hex digits; assumes valid hex digits. */
+#define loxtoi_1(p)   (*(p) <= '9'? (*(p)- '0'): (*(p)-'a'+10))
+#define loxtoi_2(p)   ((loxtoi_1(p) * 16) + loxtoi_1((p)+1))
+
+/* Returns true if P points to a lowercase hex digit. */
+#define loxdigit_p(p) !!strchr ("01234567890abcdef", *(p))
+
 
 \f
 /* Check whether the OS is in FIPS mode and record that in a module
@@ -480,31 +490,52 @@ check_binary_integrity (void)
         err = gpg_error (GPG_ERR_INTERNAL);
       else
         {
-          FILE *fp;
-  
-          fname = gcry_malloc (strlen (info.dli_fname) + 5 + 1 );
+          fname = gcry_malloc (strlen (info.dli_fname) + 1 + 5 + 1 );
           if (!fname)
             err = gpg_error_from_syserror ();
           else
             {
-              strcpy (stpcpy (fname, info.dli_fname), ".hmac");
-              fp = fopen (fname, "rb");
+              FILE *fp;
+              char *p;
+
+              /* Prefix the basename with a dot.  */
+              strcpy (fname, info.dli_fname);
+              p = strrchr (fname, '/');
+              if (p)
+                p++;
+              else
+                p = fname;
+              memmove (p+1, p, strlen (p)+1);
+              *p = '.';
+              strcat (fname, ".hmac");
+
+              /* Open the file.  */
+              fp = fopen (fname, "r");
               if (!fp)
                 err = gpg_error_from_syserror ();
               else
                 {
-                  char buffer[33];
+                  /* A buffer of 64 bytes plus one for a LF and one to
+                     detect garbage.  */
+                  unsigned char buffer[64+1+1]; 
+                  const unsigned char *s;
                   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;
-
+                  /* The HMAC files consists of lowercase hex digits
+                     only with an optional trailing linefeed.  Fail if
+                     there is any garbage.  */
+                  err = gpg_error (GPG_ERR_SELFTEST_FAILED);
+                  n = fread (buffer, 1, sizeof buffer, fp);
+                  if (n == 64 || (n == 65 && buffer[64] == '\n'))
+                    {
+                      buffer[64] = 0;
+                      for (n=0, s= buffer;
+                           n < 32 && loxdigit_p (s) && loxdigit_p (s+1);
+                           n++, s += 2)
+                        buffer[n] = loxtoi_2 (s);
+                      if ( n == 32 && !memcmp (digest, buffer, 32) )
+                        err = 0;
+                    }
                   fclose (fp);
                 }
             }